From d0a914d8adf779b771aa63cb0731e9201b99a067 Mon Sep 17 00:00:00 2001 From: "Valexa O." <46427879+valexao@users.noreply.github.com> Date: Tue, 6 Jan 2026 14:31:52 -0500 Subject: [PATCH 01/76] Update MPS Playstream event references with changes from playfab-docs (#2766) * Update MPS playstream event references with changes from playfab-docs repo * rm added file * delete old files * update ms author to be microsoft alias --- .../events/build-alias-created.md | 44 ++++++++ .../events/build-alias-deleted.md | 43 ++++++++ .../events/build-alias-updated.md | 44 ++++++++ ...r-server-requested.md => build-deleted.md} | 10 +- ...nged.md => build-region-status-changed.md} | 8 +- ...ion-updated.md => build-region-updated.md} | 8 +- .../events/build-region-utilization.md | 44 ++++++++ ...cate-deleted.md => certificate-deleted.md} | 8 +- ...te-uploaded.md => certificate-uploaded.md} | 8 +- .../api-references/events/crash-detected.md | 44 ++++++++ ...initiated.md => create-build-initiated.md} | 8 +- .../buildaliascreatedeventpayload.md | 20 ++++ .../buildaliasdeletedeventpayload.md | 19 ++++ .../buildaliasupdatedeventpayload.md | 20 ++++ ...payload.md => builddeletedeventpayload.md} | 6 +- ...> buildregionstatuschangedeventpayload.md} | 6 +- ...d.md => buildregionupdatedeventpayload.md} | 6 +- .../buildregionutilizationeventpayload.md | 25 +++++ ...d.md => certificatedeletedeventpayload.md} | 6 +- ....md => certificateuploadedeventpayload.md} | 6 +- .../data-types/crashdetectedeventpayload.md | 24 +++++ ...md => createbuildinitiatedeventpayload.md} | 6 +- ...oad.md => gameassetdeletedeventpayload.md} | 6 +- .../data-types/gamecertificatedeployed.md | 24 +++++ .../monitoringoutputsavedeventpayload.md | 24 +++++ .../data-types/secretaddedeventpayload.md | 19 ++++ .../data-types/secretdeletedeventpayload.md | 19 ++++ ...load.md => serverrequestedeventpayload.md} | 6 +- ...d.md => serverstatechangedeventpayload.md} | 6 +- ...ntpayload.md => vmassignedeventpayload.md} | 6 +- .../vmgamecertificatesdeployedeventpayload.md | 22 ++++ ....md => vmremoteusercreatedeventpayload.md} | 6 +- ....md => vmremoteuserdeletedeventpayload.md} | 6 +- .../data-types/vmstatechangeeventpayload.md | 23 ++++ ...d => vmunassignmentstartedeventpayload.md} | 6 +- ...tpayload.md => vmunhealthyeventpayload.md} | 6 +- .../events/enabled-for-title.md | 43 ++++++++ ...asset-deleted.md => game-asset-deleted.md} | 9 +- playfab-docs/api-references/events/index.md | 101 ++++++++++++------ .../events/monitoring-output-saved.md | 44 ++++++++ .../api-references/events/secret-added.md | 44 ++++++++ .../api-references/events/secret-deleted.md | 44 ++++++++ ...r-build-deleted.md => server-requested.md} | 10 +- ...ate-changed.md => server-state-changed.md} | 8 +- ...r-server-vm-assigned.md => vm-assigned.md} | 8 +- .../events/vm-game-certificates-deployed.md | 44 ++++++++ ...r-created.md => vm-remote-user-created.md} | 8 +- ...r-deleted.md => vm-remote-user-deleted.md} | 8 +- .../api-references/events/vm-state-change.md | 44 ++++++++ ...-started.md => vm-unassignment-started.md} | 9 +- ...server-vm-unhealthy.md => vm-unhealthy.md} | 9 +- playfab-docs/api-references/toc.yml | 74 ++++++++----- 52 files changed, 938 insertions(+), 161 deletions(-) create mode 100644 playfab-docs/api-references/events/build-alias-created.md create mode 100644 playfab-docs/api-references/events/build-alias-deleted.md create mode 100644 playfab-docs/api-references/events/build-alias-updated.md rename playfab-docs/api-references/events/{multiplayer-server-requested.md => build-deleted.md} (90%) rename playfab-docs/api-references/events/{multiplayer-server-build-region-status-changed.md => build-region-status-changed.md} (87%) rename playfab-docs/api-references/events/{multiplayer-server-build-region-updated.md => build-region-updated.md} (89%) create mode 100644 playfab-docs/api-references/events/build-region-utilization.md rename playfab-docs/api-references/events/{multiplayer-server-certificate-deleted.md => certificate-deleted.md} (89%) rename playfab-docs/api-references/events/{multiplayer-server-certificate-uploaded.md => certificate-uploaded.md} (89%) create mode 100644 playfab-docs/api-references/events/crash-detected.md rename playfab-docs/api-references/events/{multiplayer-server-create-build-initiated.md => create-build-initiated.md} (88%) create mode 100644 playfab-docs/api-references/events/data-types/buildaliascreatedeventpayload.md create mode 100644 playfab-docs/api-references/events/data-types/buildaliasdeletedeventpayload.md create mode 100644 playfab-docs/api-references/events/data-types/buildaliasupdatedeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerserverbuilddeletedeventpayload.md => builddeletedeventpayload.md} (70%) rename playfab-docs/api-references/events/data-types/{multiplayerserverbuildregionstatuschangedeventpayload.md => buildregionstatuschangedeventpayload.md} (74%) rename playfab-docs/api-references/events/data-types/{multiplayerserverbuildregionupdatedeventpayload.md => buildregionupdatedeventpayload.md} (74%) create mode 100644 playfab-docs/api-references/events/data-types/buildregionutilizationeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerservercertificatedeletedeventpayload.md => certificatedeletedeventpayload.md} (67%) rename playfab-docs/api-references/events/data-types/{multiplayerservercertificateuploadedeventpayload.md => certificateuploadedeventpayload.md} (66%) create mode 100644 playfab-docs/api-references/events/data-types/crashdetectedeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerservercreatebuildinitiatedeventpayload.md => createbuildinitiatedeventpayload.md} (73%) rename playfab-docs/api-references/events/data-types/{multiplayerservergameassetdeletedeventpayload.md => gameassetdeletedeventpayload.md} (67%) create mode 100644 playfab-docs/api-references/events/data-types/gamecertificatedeployed.md create mode 100644 playfab-docs/api-references/events/data-types/monitoringoutputsavedeventpayload.md create mode 100644 playfab-docs/api-references/events/data-types/secretaddedeventpayload.md create mode 100644 playfab-docs/api-references/events/data-types/secretdeletedeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerserverrequestedeventpayload.md => serverrequestedeventpayload.md} (86%) rename playfab-docs/api-references/events/data-types/{multiplayerserverstatechangedeventpayload.md => serverstatechangedeventpayload.md} (80%) rename playfab-docs/api-references/events/data-types/{multiplayerservervmassignedeventpayload.md => vmassignedeventpayload.md} (81%) create mode 100644 playfab-docs/api-references/events/data-types/vmgamecertificatesdeployedeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerservervmremoteusercreatedeventpayload.md => vmremoteusercreatedeventpayload.md} (74%) rename playfab-docs/api-references/events/data-types/{multiplayerservervmremoteuserdeletedeventpayload.md => vmremoteuserdeletedeventpayload.md} (76%) create mode 100644 playfab-docs/api-references/events/data-types/vmstatechangeeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerservervmunassignmentstartedeventpayload.md => vmunassignmentstartedeventpayload.md} (81%) rename playfab-docs/api-references/events/data-types/{multiplayerservervmunhealthyeventpayload.md => vmunhealthyeventpayload.md} (76%) create mode 100644 playfab-docs/api-references/events/enabled-for-title.md rename playfab-docs/api-references/events/{multiplayer-server-game-asset-deleted.md => game-asset-deleted.md} (89%) create mode 100644 playfab-docs/api-references/events/monitoring-output-saved.md create mode 100644 playfab-docs/api-references/events/secret-added.md create mode 100644 playfab-docs/api-references/events/secret-deleted.md rename playfab-docs/api-references/events/{multiplayer-server-build-deleted.md => server-requested.md} (87%) rename playfab-docs/api-references/events/{multiplayer-server-state-changed.md => server-state-changed.md} (90%) rename playfab-docs/api-references/events/{multiplayer-server-vm-assigned.md => vm-assigned.md} (90%) create mode 100644 playfab-docs/api-references/events/vm-game-certificates-deployed.md rename playfab-docs/api-references/events/{multiplayer-server-vm-remote-user-created.md => vm-remote-user-created.md} (88%) rename playfab-docs/api-references/events/{multiplayer-server-vm-remote-user-deleted.md => vm-remote-user-deleted.md} (88%) create mode 100644 playfab-docs/api-references/events/vm-state-change.md rename playfab-docs/api-references/events/{multiplayer-server-vm-unassignment-started.md => vm-unassignment-started.md} (88%) rename playfab-docs/api-references/events/{multiplayer-server-vm-unhealthy.md => vm-unhealthy.md} (89%) diff --git a/playfab-docs/api-references/events/build-alias-created.md b/playfab-docs/api-references/events/build-alias-created.md new file mode 100644 index 000000000..4b1c0ab8d --- /dev/null +++ b/playfab-docs/api-references/events/build-alias-created.md @@ -0,0 +1,44 @@ +--- +title: build_alias_created +author: valexao +description: build_alias_created event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# build_alias_created + +This event is triggered when a multiplayer server build alias is created. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[BuildAliasCreatedEventPayload](data-types/buildaliascreatedeventpayload.md)|The multiplayer server build alias created event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/build-alias-deleted.md b/playfab-docs/api-references/events/build-alias-deleted.md new file mode 100644 index 000000000..5a96b8b54 --- /dev/null +++ b/playfab-docs/api-references/events/build-alias-deleted.md @@ -0,0 +1,43 @@ +--- +title: build_alias_deleted +author: valexao +description: build_alias_deleted event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# build_alias_deleted + +This event is triggered when a multiplayer server build alias is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[BuildAliasDeletedEventPayload](data-types/buildaliasdeletedeventpayload.md)|The multiplayer server build alias deleted event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| diff --git a/playfab-docs/api-references/events/build-alias-updated.md b/playfab-docs/api-references/events/build-alias-updated.md new file mode 100644 index 000000000..ae3275574 --- /dev/null +++ b/playfab-docs/api-references/events/build-alias-updated.md @@ -0,0 +1,44 @@ +--- +title: build_alias_updated +author: valexao +description: build_alias_updated event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# build_alias_updated + +This event is triggered when a multiplayer server build alias is updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[BuildAliasUpdatedEventPayload](data-types/buildaliasupdatedeventpayload.md)|The multiplayer server build alias updated event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-requested.md b/playfab-docs/api-references/events/build-deleted.md similarity index 90% rename from playfab-docs/api-references/events/multiplayer-server-requested.md rename to playfab-docs/api-references/events/build-deleted.md index 30a437724..1a1ede519 100644 --- a/playfab-docs/api-references/events/multiplayer-server-requested.md +++ b/playfab-docs/api-references/events/build-deleted.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_requested +title: build_deleted author: joannaleecy -description: multiplayer_server_requested event. +description: build_deleted event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,9 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_requested +# build_deleted + +This event is triggered when a multiplayer server build is deleted. ## Properties @@ -19,7 +21,7 @@ ms.localizationpriority: medium |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerRequestedEventPayload](data-types/multiplayerserverrequestedeventpayload.md)|The multiplayer server requested event payload.| +|Payload|[BuildDeletedEventPayload](data-types/builddeletedeventpayload.md)|The multiplayer server build deleted event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-build-region-status-changed.md b/playfab-docs/api-references/events/build-region-status-changed.md similarity index 87% rename from playfab-docs/api-references/events/multiplayer-server-build-region-status-changed.md rename to playfab-docs/api-references/events/build-region-status-changed.md index ece9c11ce..55c945293 100644 --- a/playfab-docs/api-references/events/multiplayer-server-build-region-status-changed.md +++ b/playfab-docs/api-references/events/build-region-status-changed.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_build_region_status_changed +title: build_region_status_changed author: joannaleecy -description: multiplayer_server_build_region_status_changed event. +description: build_region_status_changed event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_build_region_status_changed +# build_region_status_changed This event is triggered when a multiplayer server's build region status is changed. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server's build region status is chang |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerBuildRegionStatusChangedEventPayload](data-types/multiplayerserverbuildregionstatuschangedeventpayload.md)|The multiplayer server build region status changed event payload.| +|Payload|[BuildRegionStatusChangedEventPayload](data-types/buildregionstatuschangedeventpayload.md)|The multiplayer server build region status changed event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-build-region-updated.md b/playfab-docs/api-references/events/build-region-updated.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-build-region-updated.md rename to playfab-docs/api-references/events/build-region-updated.md index 049fc51ec..56dbe2c75 100644 --- a/playfab-docs/api-references/events/multiplayer-server-build-region-updated.md +++ b/playfab-docs/api-references/events/build-region-updated.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_build_region_updated +title: build_region_updated author: joannaleecy -description: multiplayer_server_build_region_updated event. +description: build_region_updated event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_build_region_updated +# build_region_updated This event is triggered when a multiplayer server build region is updated. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server build region is updated. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerBuildRegionUpdatedEventPayload](data-types/multiplayerserverbuildregionupdatedeventpayload.md)|The multiplayer server build region updated event payload.| +|Payload|[BuildRegionUpdatedEventPayload](data-types/buildregionupdatedeventpayload.md)|The multiplayer server build region updated event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/build-region-utilization.md b/playfab-docs/api-references/events/build-region-utilization.md new file mode 100644 index 000000000..2c71f7e1e --- /dev/null +++ b/playfab-docs/api-references/events/build-region-utilization.md @@ -0,0 +1,44 @@ +--- +title: build_region_utilization +author: valexao +description: build_region_utilization event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# build_region_utilization + +This event is triggered to display the utilization of servers for a build in each region. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[BuildRegionUtilizationEventPayload](data-types/buildregionutilizationeventpayload.md)|The multiplayer server build region utilization event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-certificate-deleted.md b/playfab-docs/api-references/events/certificate-deleted.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-certificate-deleted.md rename to playfab-docs/api-references/events/certificate-deleted.md index 3c3b36856..421b229df 100644 --- a/playfab-docs/api-references/events/multiplayer-server-certificate-deleted.md +++ b/playfab-docs/api-references/events/certificate-deleted.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_certificate_deleted +title: certificate_deleted author: joannaleecy -description: multiplayer_server_certificate_deleted event. +description: certificate_deleted event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_certificate_deleted +# certificate_deleted This event is triggered when a multiplayer server certificate is deleted. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server certificate is deleted. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerCertificateDeletedEventPayload](data-types/multiplayerservercertificatedeletedeventpayload.md)|The multiplayer server certificate deleted event payload.| +|Payload|[CertificateDeletedEventPayload](data-types/certificatedeletedeventpayload.md)|The multiplayer server certificate deleted event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-certificate-uploaded.md b/playfab-docs/api-references/events/certificate-uploaded.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-certificate-uploaded.md rename to playfab-docs/api-references/events/certificate-uploaded.md index f7a797151..d54bc860a 100644 --- a/playfab-docs/api-references/events/multiplayer-server-certificate-uploaded.md +++ b/playfab-docs/api-references/events/certificate-uploaded.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_certificate_uploaded +title: certificate_uploaded author: joannaleecy -description: multiplayer_server_certificate_uploaded event. +description: certificate_uploaded event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_certificate_uploaded +# certificate_uploaded This event is triggered when a multiplayer server certificate is uploaded. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server certificate is uploaded. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerCertificateUploadedEventPayload](data-types/multiplayerservercertificateuploadedeventpayload.md)|The multiplayer server certificate uploaded event payload.| +|Payload|[CertificateUploadedEventPayload](data-types/certificateuploadedeventpayload.md)|The multiplayer server certificate uploaded event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/crash-detected.md b/playfab-docs/api-references/events/crash-detected.md new file mode 100644 index 000000000..dddec0188 --- /dev/null +++ b/playfab-docs/api-references/events/crash-detected.md @@ -0,0 +1,44 @@ +--- +title: crash_detected +author: valexao +description: crash_detected event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# crash_detected + +This event triggered when a crash dump is found on a terminating server. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[CrashDetectedEventPayload](data-types/crashdetectedeventpayload.md)|The multiplayer server crash detected event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-create-build-initiated.md b/playfab-docs/api-references/events/create-build-initiated.md similarity index 88% rename from playfab-docs/api-references/events/multiplayer-server-create-build-initiated.md rename to playfab-docs/api-references/events/create-build-initiated.md index c0065eeda..92253f0d0 100644 --- a/playfab-docs/api-references/events/multiplayer-server-create-build-initiated.md +++ b/playfab-docs/api-references/events/create-build-initiated.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_create_build_initiated +title: create_build_initiated author: joannaleecy -description: multiplayer_server_create_build_initiated event. +description: create_build_initiated event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_create_build_initiated +# create_build_initiated This event is triggered when a multiplayer server build is initiated. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server build is initiated. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerCreateBuildInitiatedEventPayload](data-types/multiplayerservercreatebuildinitiatedeventpayload.md)|The multiplayer server create build initiated event payload.| +|Payload|[CreateBuildInitiatedEventPayload](data-types/createbuildinitiatedeventpayload.md)|The multiplayer server create build initiated event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/data-types/buildaliascreatedeventpayload.md b/playfab-docs/api-references/events/data-types/buildaliascreatedeventpayload.md new file mode 100644 index 000000000..c6cb27d95 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/buildaliascreatedeventpayload.md @@ -0,0 +1,20 @@ +--- +title: BuildAliasCreatedEventPayload +author: valexao +description: BuildAliasCreatedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# BuildAliasCreatedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|AliasName|String|The name of the build alias that was created.| +|AliasId|String|The Guid ID of the build alias that was created.| diff --git a/playfab-docs/api-references/events/data-types/buildaliasdeletedeventpayload.md b/playfab-docs/api-references/events/data-types/buildaliasdeletedeventpayload.md new file mode 100644 index 000000000..a585f18ff --- /dev/null +++ b/playfab-docs/api-references/events/data-types/buildaliasdeletedeventpayload.md @@ -0,0 +1,19 @@ +--- +title: BuildAliasDeletedEventPayload +author: valexao +description: BuildAliasDeletedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# BuildAliasDeletedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|AliasId|String|The Guid ID of the build alias that was deleted.| diff --git a/playfab-docs/api-references/events/data-types/buildaliasupdatedeventpayload.md b/playfab-docs/api-references/events/data-types/buildaliasupdatedeventpayload.md new file mode 100644 index 000000000..67c1eab2e --- /dev/null +++ b/playfab-docs/api-references/events/data-types/buildaliasupdatedeventpayload.md @@ -0,0 +1,20 @@ +--- +title: BuildAliasUpdatedEventPayload +author: valexao +description: BuildAliasUpdatedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# BuildAliasUpdatedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|AliasName|String|The name of the build alias that was updated.| +|AliasId|String|The Guid ID of the build alias that was updated.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverbuilddeletedeventpayload.md b/playfab-docs/api-references/events/data-types/builddeletedeventpayload.md similarity index 70% rename from playfab-docs/api-references/events/data-types/multiplayerserverbuilddeletedeventpayload.md rename to playfab-docs/api-references/events/data-types/builddeletedeventpayload.md index 264ec7491..50343df28 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverbuilddeletedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/builddeletedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerBuildDeletedEventPayload +title: BuildDeletedEventPayload author: joannaleecy -description: MultiplayerServerBuildDeletedEventPayload data type. +description: BuildDeletedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerBuildDeletedEventPayload +# BuildDeletedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverbuildregionstatuschangedeventpayload.md b/playfab-docs/api-references/events/data-types/buildregionstatuschangedeventpayload.md similarity index 74% rename from playfab-docs/api-references/events/data-types/multiplayerserverbuildregionstatuschangedeventpayload.md rename to playfab-docs/api-references/events/data-types/buildregionstatuschangedeventpayload.md index 58c5bf085..d55fae1eb 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverbuildregionstatuschangedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/buildregionstatuschangedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerBuildRegionStatusChangedEventPayload +title: BuildRegionStatusChangedEventPayload author: joannaleecy -description: MultiplayerServerBuildRegionStatusChangedEventPayload data type. +description: BuildRegionStatusChangedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerBuildRegionStatusChangedEventPayload +# BuildRegionStatusChangedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverbuildregionupdatedeventpayload.md b/playfab-docs/api-references/events/data-types/buildregionupdatedeventpayload.md similarity index 74% rename from playfab-docs/api-references/events/data-types/multiplayerserverbuildregionupdatedeventpayload.md rename to playfab-docs/api-references/events/data-types/buildregionupdatedeventpayload.md index 46c25e274..49533b362 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverbuildregionupdatedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/buildregionupdatedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerBuildRegionUpdatedEventPayload +title: BuildRegionUpdatedEventPayload author: joannaleecy -description: MultiplayerServerBuildRegionUpdatedEventPayload data type. +description: BuildRegionUpdatedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerBuildRegionUpdatedEventPayload +# BuildRegionUpdatedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/buildregionutilizationeventpayload.md b/playfab-docs/api-references/events/data-types/buildregionutilizationeventpayload.md new file mode 100644 index 000000000..f59a30494 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/buildregionutilizationeventpayload.md @@ -0,0 +1,25 @@ +--- +title: BuildRegionUtilizationEventPayload +author: valexao +description: BuildRegionUtilizationEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# BuildRegionUtilizationEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The guid string ID of the multiplayer server build that regions were updated on.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|Active|Int|The number of active servers.| +|StandingBy|Int|The number of standingby servers.| +|Propping|Int|The number of servers still downloading game resources.| +|Total|Int|The total number of servers.| +|VmCount|Int|The total number of running virtual machines.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerservercertificatedeletedeventpayload.md b/playfab-docs/api-references/events/data-types/certificatedeletedeventpayload.md similarity index 67% rename from playfab-docs/api-references/events/data-types/multiplayerservercertificatedeletedeventpayload.md rename to playfab-docs/api-references/events/data-types/certificatedeletedeventpayload.md index 0de591ca1..a6c2fd2db 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservercertificatedeletedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/certificatedeletedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerCertificateDeletedEventPayload +title: CertificateDeletedEventPayload author: joannaleecy -description: MultiplayerServerCertificateDeletedEventPayload data type. +description: CertificateDeletedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerCertificateDeletedEventPayload +# CertificateDeletedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservercertificateuploadedeventpayload.md b/playfab-docs/api-references/events/data-types/certificateuploadedeventpayload.md similarity index 66% rename from playfab-docs/api-references/events/data-types/multiplayerservercertificateuploadedeventpayload.md rename to playfab-docs/api-references/events/data-types/certificateuploadedeventpayload.md index e85c07fac..cd663316e 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservercertificateuploadedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/certificateuploadedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MMultiplayerServerCertificateUploadedEventPayload +title: CertificateUploadedEventPayload author: joannaleecy -description: MultiplayerServerCertificateUploadedEventPayload data type. +description: CertificateUploadedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerCertificateUploadedEventPayload +# CertificateUploadedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/crashdetectedeventpayload.md b/playfab-docs/api-references/events/data-types/crashdetectedeventpayload.md new file mode 100644 index 000000000..38ce9d734 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/crashdetectedeventpayload.md @@ -0,0 +1,24 @@ +--- +title: CrashDetectedEventPayload +author: valexao +description: CrashDetectedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# CrashDetectedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The guid string ID of the multiplayer server build that regions were updated on.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|ServerId|String|The guid string ID of the session.| +|VmId|String|The virtual machine ID the multiplayer server is located on.| +|CrashDumpUploaded|bool|If true, the crash dump was uploaded with the server's logs.| +|CrashDumpStatus|String|The reason a crash dump wasn't uploaded. If null, assume no crash dump was found.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerservercreatebuildinitiatedeventpayload.md b/playfab-docs/api-references/events/data-types/createbuildinitiatedeventpayload.md similarity index 73% rename from playfab-docs/api-references/events/data-types/multiplayerservercreatebuildinitiatedeventpayload.md rename to playfab-docs/api-references/events/data-types/createbuildinitiatedeventpayload.md index 0a3b999be..d4827582c 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservercreatebuildinitiatedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/createbuildinitiatedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerCreateBuildInitiatedEventPayload +title: CreateBuildInitiatedEventPayload author: joannaleecy -description: MultiplayerServerCreateBuildInitiatedEventPayload data type. +description: CreateBuildInitiatedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerCreateBuildInitiatedEventPayload +# CreateBuildInitiatedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservergameassetdeletedeventpayload.md b/playfab-docs/api-references/events/data-types/gameassetdeletedeventpayload.md similarity index 67% rename from playfab-docs/api-references/events/data-types/multiplayerservergameassetdeletedeventpayload.md rename to playfab-docs/api-references/events/data-types/gameassetdeletedeventpayload.md index 3c90072f2..12cdf018b 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservergameassetdeletedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/gameassetdeletedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerGameAssetDeletedEventPayload +title: GameAssetDeletedEventPayload author: joannaleecy -description: MMultiplayerServerGameAssetDeletedEventPayload data type. +description: GameAssetDeletedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerGameAssetDeletedEventPayload +# GameAssetDeletedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/gamecertificatedeployed.md b/playfab-docs/api-references/events/data-types/gamecertificatedeployed.md new file mode 100644 index 000000000..c5356515f --- /dev/null +++ b/playfab-docs/api-references/events/data-types/gamecertificatedeployed.md @@ -0,0 +1,24 @@ +--- +title: GameCertificateDeployed +author: valexao +description: GameCertificateDeployed data type. +ms.author: vorelien +ms.date: 12/10/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# GameCertificateDeployed + +Information about the game certificate deployed in the VM. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Name|String|The certificate name.| +|Thumbprint|String|The certificate thumbprint.| +|Version|String|The certificate version.| +|Expiration|String|The certificate expiration date.| diff --git a/playfab-docs/api-references/events/data-types/monitoringoutputsavedeventpayload.md b/playfab-docs/api-references/events/data-types/monitoringoutputsavedeventpayload.md new file mode 100644 index 000000000..08c74dc0c --- /dev/null +++ b/playfab-docs/api-references/events/data-types/monitoringoutputsavedeventpayload.md @@ -0,0 +1,24 @@ +--- +title: MonitoringOutputSavedEventPayload +author: valexao +description: MonitoringOutputSavedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# MonitoringOutputSavedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The Guid string ID of the build.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|ServerId|String|The multiplayer server ID.| +|SessionId|String|The Guid string ID of the session.| +|VmId|String|The virtual machine ID the multiplayer server is located on.| +|IsVmLevel|bool|True if the monitoring output was not associated with a running server.| diff --git a/playfab-docs/api-references/events/data-types/secretaddedeventpayload.md b/playfab-docs/api-references/events/data-types/secretaddedeventpayload.md new file mode 100644 index 000000000..07c3fa7c3 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/secretaddedeventpayload.md @@ -0,0 +1,19 @@ +--- +title: SecretAddedEventPayload +author: valexao +description: SecretAddedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# SecretAddedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|SecretName|String|The name of the secret that was added.| diff --git a/playfab-docs/api-references/events/data-types/secretdeletedeventpayload.md b/playfab-docs/api-references/events/data-types/secretdeletedeventpayload.md new file mode 100644 index 000000000..83aa53d1a --- /dev/null +++ b/playfab-docs/api-references/events/data-types/secretdeletedeventpayload.md @@ -0,0 +1,19 @@ +--- +title: SecretDeletedEventPayload +author: valexao +description: SecretDeletedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# SecretDeletedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|SecretName|String|The name of the secret that was deleted.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverrequestedeventpayload.md b/playfab-docs/api-references/events/data-types/serverrequestedeventpayload.md similarity index 86% rename from playfab-docs/api-references/events/data-types/multiplayerserverrequestedeventpayload.md rename to playfab-docs/api-references/events/data-types/serverrequestedeventpayload.md index d0fbbf6d0..d710af185 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverrequestedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/serverrequestedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerRequestedEventPayload +title: ServerRequestedEventPayload author: joannaleecy -description: MultiplayerServerRequestedEventPayload data type. +description: ServerRequestedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerRequestedEventPayload +# ServerRequestedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverstatechangedeventpayload.md b/playfab-docs/api-references/events/data-types/serverstatechangedeventpayload.md similarity index 80% rename from playfab-docs/api-references/events/data-types/multiplayerserverstatechangedeventpayload.md rename to playfab-docs/api-references/events/data-types/serverstatechangedeventpayload.md index ff1961a84..82840961c 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverstatechangedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/serverstatechangedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerStateChangedEventPayload +title: ServerStateChangedEventPayload author: joannaleecy -description: MultiplayerServerStateChangedEventPayload data type. +description: ServerStateChangedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerStateChangedEventPayload +# ServerStateChangedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmassignedeventpayload.md b/playfab-docs/api-references/events/data-types/vmassignedeventpayload.md similarity index 81% rename from playfab-docs/api-references/events/data-types/multiplayerservervmassignedeventpayload.md rename to playfab-docs/api-references/events/data-types/vmassignedeventpayload.md index 051ec25a4..71ed8541c 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmassignedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmassignedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmAssignedEventPayload +title: VmAssignedEventPayload author: joannaleecy -description: MultiplayerServerVmAssignedEventPayload data type. +description: VmAssignedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmAssignedEventPayload +# VmAssignedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/vmgamecertificatesdeployedeventpayload.md b/playfab-docs/api-references/events/data-types/vmgamecertificatesdeployedeventpayload.md new file mode 100644 index 000000000..bf2559090 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/vmgamecertificatesdeployedeventpayload.md @@ -0,0 +1,22 @@ +--- +title: VmGameCertificatesDeployedEventPayload +author: valexao +description: VmGameCertificatesDeployedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# VmGameCertificatesDeployedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The GUID string ID of the build.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|VmId|String|The ID of the virtual machine that was assigned.| +|GameCertificates|[List\](gamecertificatedeployed.md)|The list of game certificates deployed.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmremoteusercreatedeventpayload.md b/playfab-docs/api-references/events/data-types/vmremoteusercreatedeventpayload.md similarity index 74% rename from playfab-docs/api-references/events/data-types/multiplayerservervmremoteusercreatedeventpayload.md rename to playfab-docs/api-references/events/data-types/vmremoteusercreatedeventpayload.md index 1b8cfcaad..e8b5f7a32 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmremoteusercreatedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmremoteusercreatedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmRemoteUserCreatedEventPayload +title: VmRemoteUserCreatedEventPayload author: joannaleecy -description: MultiplayerServerVmRemoteUserCreatedEventPayload data type. +description: VmRemoteUserCreatedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmRemoteUserCreatedEventPayload +# VmRemoteUserCreatedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmremoteuserdeletedeventpayload.md b/playfab-docs/api-references/events/data-types/vmremoteuserdeletedeventpayload.md similarity index 76% rename from playfab-docs/api-references/events/data-types/multiplayerservervmremoteuserdeletedeventpayload.md rename to playfab-docs/api-references/events/data-types/vmremoteuserdeletedeventpayload.md index 23f32a80a..8f32e251a 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmremoteuserdeletedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmremoteuserdeletedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmRemoteUserDeletedEventPayload +title: VmRemoteUserDeletedEventPayload author: joannaleecy -description: MultiplayerServerVmRemoteUserDeletedEventPayload data type. +description: VmRemoteUserDeletedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmRemoteUserDeletedEventPayload +# VmRemoteUserDeletedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/vmstatechangeeventpayload.md b/playfab-docs/api-references/events/data-types/vmstatechangeeventpayload.md new file mode 100644 index 000000000..76a303e7a --- /dev/null +++ b/playfab-docs/api-references/events/data-types/vmstatechangeeventpayload.md @@ -0,0 +1,23 @@ +--- +title: VmStateChangeEventPayload +author: valexao +description: VmStateChangeEventPayload data type. +ms.author: vorelien +ms.date: 12/10/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# VmStateChangeEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The guid string ID of the multiplayer server build that regions were updated on.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|VmId|String|The virtual machine ID of the multiplayer vm.| +|State|String|The multiplayer virtual machine's state to report on.| +|DurationSeconds|ulong|The amount of time spent getting to this state.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmunassignmentstartedeventpayload.md b/playfab-docs/api-references/events/data-types/vmunassignmentstartedeventpayload.md similarity index 81% rename from playfab-docs/api-references/events/data-types/multiplayerservervmunassignmentstartedeventpayload.md rename to playfab-docs/api-references/events/data-types/vmunassignmentstartedeventpayload.md index bc7181532..4c6ebc46e 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmunassignmentstartedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmunassignmentstartedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmUnassignmentStartedEventPayload +title: VmUnassignmentStartedEventPayload author: joannaleecy -description: MultiplayerServerVmUnassignmentStartedEventPayload data type. +description: VmUnassignmentStartedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmUnassignmentStartedEventPayload +# VmUnassignmentStartedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmunhealthyeventpayload.md b/playfab-docs/api-references/events/data-types/vmunhealthyeventpayload.md similarity index 76% rename from playfab-docs/api-references/events/data-types/multiplayerservervmunhealthyeventpayload.md rename to playfab-docs/api-references/events/data-types/vmunhealthyeventpayload.md index a02a85421..c0c3f5898 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmunhealthyeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmunhealthyeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmUnhealthyEventPayload +title: VmUnhealthyEventPayload author: joannaleecy -description: MultiplayerServerVmUnhealthyEventPayload data type. +description: VmUnhealthyEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmUnhealthyEventPayload +# VmUnhealthyEventPayload ## Properties diff --git a/playfab-docs/api-references/events/enabled-for-title.md b/playfab-docs/api-references/events/enabled-for-title.md new file mode 100644 index 000000000..55b2b7094 --- /dev/null +++ b/playfab-docs/api-references/events/enabled-for-title.md @@ -0,0 +1,43 @@ +--- +title: enabled_for_title +author: valexao +description: enabled_for_title event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# enabled_for_title + +This event is triggered when a title enables PlayFab multiplayer servers. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-game-asset-deleted.md b/playfab-docs/api-references/events/game-asset-deleted.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-game-asset-deleted.md rename to playfab-docs/api-references/events/game-asset-deleted.md index dcbbecbdd..f966cb5b4 100644 --- a/playfab-docs/api-references/events/multiplayer-server-game-asset-deleted.md +++ b/playfab-docs/api-references/events/game-asset-deleted.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_game_asset_deleted +title: game_asset_deleted author: joannaleecy -description: multiplayer_server_game_asset_deleted event. +description: game_asset_deleted event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,8 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_game_asset_deleted - +# game_asset_deleted This event is triggered when a multiplayer server game asset is deleted. ## Properties @@ -21,7 +20,7 @@ This event is triggered when a multiplayer server game asset is deleted. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerGameAssetDeletedEventPayload](data-types/multiplayerservergameassetdeletedeventpayload.md)|The multiplayer server game asset deleted event payload.| +|Payload|[GameAssetDeletedEventPayload](data-types/gameassetdeletedeventpayload.md)|The multiplayer server game asset deleted event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 95c293b53..4b6c1d4d7 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -81,66 +81,101 @@ Each event type has a set of properties that are included as part of event's dat - [matchmaking_user_ticket_invite](matchmaking-user-ticket-invite.md) This event is triggered when a ticket with an invited user is created. The event will be sent to the invited user. -- [multiplayer_server_build_deleted](multiplayer-server-build-deleted.md) +- [studio_created](studio-created.md) + This event is triggered when a studio is created. + +- [studio_user_added](studio-user-added.md) + This event is triggered when a user accepts a studio invitation. + +- [studio_user_invited](studio-user-invited.md) + This event is triggered when a user is invited to a studio. + +- [studio_user_removed](studio-user-removed.md) + This event is triggered when a user is removed from a studio. + +- [tenancy_connector_onboard](tenancy-connector-onboard.md) + This event is triggered when a tenancy connector is onboarded. + +- [studio_tier_updated](studio-tier-updated.md) + This event is triggered when a studio tier is updated. + +## Multiplayer Servers + +- [build_alias_created](build-alias-created.md) + This event is triggered when a multiplayer server build alias is created. + +- [build_alias_deleted](build-alias-deleted.md) + This event is triggered when a multiplayer server build alias is deleted. + +- [build_alias_updated](build-alias-updated.md) + This event is triggered when a multiplayer server build alias is updated. + +- [build_deleted](build-deleted.md) This event is triggered when a multiplayer server build is deleted. -- [multiplayer_server_build_region_status_changed](multiplayer-server-build-region-status-changed.md) +- [build_region_status_changed](build-region-status-changed.md) This event is triggered when a multiplayer server's build region status is changed. -- [multiplayer_server_build_region_updated](multiplayer-server-build-region-updated.md) +- [build_region_updated](build-region-updated.md) This event is triggered when a multiplayer server build region is updated. -- [multiplayer_server_certificate_deleted](multiplayer-server-certificate-deleted.md) +- [build_region_utilization](build-region-utilization.md) + This event is triggered to display the utilization of servers for a build in each region. + +- [certificate_deleted](certificate-deleted.md) This event is triggered when a multiplayer server certificate is deleted. -- [multiplayer_server_certificate_uploaded](multiplayer-server-certificate-uploaded.md) +- [certificate_uploaded](certificate-uploaded.md) This event is triggered when a multiplayer server certificate is uploaded. -- [multiplayer_server_create_build_initiated](multiplayer-server-create-build-initiated.md) +- [crash_detected](crash-detected.md) + This event triggered when a crash dump is found on a terminating server. + +- [create_build_initiated](create-build-initiated.md) This event is triggered when a multiplayer server build is initiated. -- [multiplayer_server_game_asset_deleted](multiplayer-server-game-asset-deleted.md) +- [enabled_for_title](enabled-for-title.md) + This event is triggered when a title enables PlayFab servers + +- [game_asset_deleted](game-asset-deleted.md) This event is triggered when a multiplayer server game asset is deleted. -- [multiplayer_server_requested](multiplayer-server-requested.md) - This event is triggered when a multiplayer server shutdown is requested. +- [monitoring_output_saved](monitoring-output-saved.md) + This event is triggered when the output of a monitoring application has been saved and can be downloaded. + +- [secret_added](secret-added.md) + This event is triggered when a multiplayer server secret is added. + +- [secret_deleted](secret-deleted.md) + This event is triggered when a multiplayer server secret is deleted. -- [multiplayer_server_state_changed](multiplayer-server-state-changed.md) +- [server_requested](server-requested.md) + This event is triggered when a multiplayer server is requested. + +- [server_state_changed](server-state-changed.md) This event is triggered when a multiplayer server's state is changed. -- [multiplayer_server_vm_assigned](multiplayer-server-vm-assigned.md) +- [vm_assigned](vm-assigned.md) This event is triggered when a virtual machine is assigned to a multiplayer server build. -- [multiplayer_server_vm_remote_user_created](multiplayer-server-vm-remote-user-created.md) +- [vm_game_certificates_deployed](vm-game-certificates-deployed.md) + This event is triggered when game certificates are deployed in a game virtual machine. + +- [vm_remote_user_created](vm-remote-user-created.md) This event is triggered when a multiplayer server virtual machine remote user is created. -- [multiplayer_server_vm_remote_user_deleted](multiplayer-server-vm-remote-user-deleted.md) +- [vm_remote_user_deleted](vm-remote-user-deleted.md) This event is triggered when a multiplayer server virtual machine remote user is deleted. -- [multiplayer_server_vm_unassignment_started](multiplayer-server-vm-unassignment-started.md) +- [vm_state_change](vm-state-change.md) + This event is triggered when a multiplayer virtual machine's state is changed. + +- [vm_unassignment_started](vm-unassignment-started.md) This event is triggered when a virtual machine is unassigned from a multiplayer server build. -- [multiplayer_server_vm_unhealthy](multiplayer-server-vm-unhealthy.md) +- [vm_unhealthy](vm-unhealthy.md) This event is triggered when a virtual machine is found to be unhealthy. -- [studio_created](studio-created.md) - This event is triggered when a studio is created. - -- [studio_user_added](studio-user-added.md) - This event is triggered when a user accepts a studio invitation. - -- [studio_user_invited](studio-user-invited.md) - This event is triggered when a user is invited to a studio. - -- [studio_user_removed](studio-user-removed.md) - This event is triggered when a user is removed from a studio. - -- [tenancy_connector_onboard](tenancy-connector-onboard.md) - This event is triggered when a tenancy connector is onboarded. - -- [studio_tier_updated](studio-tier-updated.md) - This event is triggered when a studio tier is updated. - ## Catalog - [item_created](item-created.md) diff --git a/playfab-docs/api-references/events/monitoring-output-saved.md b/playfab-docs/api-references/events/monitoring-output-saved.md new file mode 100644 index 000000000..c1ac05abc --- /dev/null +++ b/playfab-docs/api-references/events/monitoring-output-saved.md @@ -0,0 +1,44 @@ +--- +title: monitoring_output_saved +author: valexao +description: monitoring_output_saved event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# monitoring_output_saved + +This event is triggered when the output of a monitoring application has been saved and can be downloaded. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[MonitoringOutputSavedEventPayload](data-types/monitoringoutputsavedeventpayload.md)|The multiplayer server monitoring output saved event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/secret-added.md b/playfab-docs/api-references/events/secret-added.md new file mode 100644 index 000000000..5d583087f --- /dev/null +++ b/playfab-docs/api-references/events/secret-added.md @@ -0,0 +1,44 @@ +--- +title: secret_added +author: valexao +description: secret_added event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# secret_added + +This event is triggered when a multiplayer server secret is added. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[SecretAddedEventPayload](data-types/secretaddedeventpayload.md)|The multiplayer server secret added event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/secret-deleted.md b/playfab-docs/api-references/events/secret-deleted.md new file mode 100644 index 000000000..f50df6f67 --- /dev/null +++ b/playfab-docs/api-references/events/secret-deleted.md @@ -0,0 +1,44 @@ +--- +title: secret_deleted +author: valexao +description: secret_deleted event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# secret_deleted + +This event is triggered when a multiplayer server secret is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[SecretDeletedEventPayload](data-types/secretdeletedeventpayload.md)|The multiplayer server secret deleted event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-build-deleted.md b/playfab-docs/api-references/events/server-requested.md similarity index 87% rename from playfab-docs/api-references/events/multiplayer-server-build-deleted.md rename to playfab-docs/api-references/events/server-requested.md index 9871653e3..47fd0cae3 100644 --- a/playfab-docs/api-references/events/multiplayer-server-build-deleted.md +++ b/playfab-docs/api-references/events/server-requested.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_build_deleted +title: server_requested author: joannaleecy -description: multiplayer_server_build_deleted event. +description: server_requested event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_build_deleted +# server_requested -This event is triggered when a multiplayer server build is deleted. +This event is triggered when a multiplayer server is requested. ## Properties @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server build is deleted. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerBuildDeletedEventPayload](data-types/multiplayerserverbuilddeletedeventpayload.md)|The multiplayer server build region deleted event payload.| +|Payload|[ServerRequestedEventPayload](data-types/serverrequestedeventpayload.md)|The multiplayer server requested event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-state-changed.md b/playfab-docs/api-references/events/server-state-changed.md similarity index 90% rename from playfab-docs/api-references/events/multiplayer-server-state-changed.md rename to playfab-docs/api-references/events/server-state-changed.md index 5750987f8..4386c2bae 100644 --- a/playfab-docs/api-references/events/multiplayer-server-state-changed.md +++ b/playfab-docs/api-references/events/server-state-changed.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_state_changed +title: server_state_changed author: joannaleecy -description: multiplayer_server_state_changed event. +description: server_state_changed event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_state_changed +# server_state_changed This event is triggered when a multiplayer server's state is changed. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server's state is changed. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerStateChangedEventPayload](data-types/multiplayerserverstatechangedeventpayload.md)|The multiplayer server state changed event payload.| +|Payload|[ServerStateChangedEventPayload](data-types/serverstatechangedeventpayload.md)|The multiplayer server state changed event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-assigned.md b/playfab-docs/api-references/events/vm-assigned.md similarity index 90% rename from playfab-docs/api-references/events/multiplayer-server-vm-assigned.md rename to playfab-docs/api-references/events/vm-assigned.md index 7f68abd32..5a3ceedc1 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-assigned.md +++ b/playfab-docs/api-references/events/vm-assigned.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_assigned +title: vm_assigned author: joannaleecy -description: multiplayer_server_vm_assigned event. +description: vm_assigned event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_assigned +# vm_assigned This event is triggered when a virtual machine is assigned to a multiplayer server build. @@ -21,7 +21,7 @@ This event is triggered when a virtual machine is assigned to a multiplayer serv |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmAssignedEventPayload](data-types/multiplayerservervmassignedeventpayload.md)|The multiplayer server virtual machine assigned event payload.| +|Payload|[VmAssignedEventPayload](data-types/vmassignedeventpayload.md)|The multiplayer server virtual machine assigned event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/vm-game-certificates-deployed.md b/playfab-docs/api-references/events/vm-game-certificates-deployed.md new file mode 100644 index 000000000..03f799863 --- /dev/null +++ b/playfab-docs/api-references/events/vm-game-certificates-deployed.md @@ -0,0 +1,44 @@ +--- +title: vm_game_certificates_deployed +author: valexao +description: vm_game_certificates_deployed event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# vm_game_certificates_deployed + +This event is triggered when game certificates are deployed in a game virtual machine. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[VmGameCertificatesDeployedEventPayload](data-types/vmgamecertificatesdeployedeventpayload.md)|The multiplayer server vm game certificates deployed event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-remote-user-created.md b/playfab-docs/api-references/events/vm-remote-user-created.md similarity index 88% rename from playfab-docs/api-references/events/multiplayer-server-vm-remote-user-created.md rename to playfab-docs/api-references/events/vm-remote-user-created.md index 032231d44..640701d81 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-remote-user-created.md +++ b/playfab-docs/api-references/events/vm-remote-user-created.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_remote_user_created +title: vm_remote_user_created author: joannaleecy -description: multiplayer_server_vm_remote_user_created event. +description: vm_remote_user_created event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_remote_user_created +# vm_remote_user_created This event is triggered when a multiplayer server virtual machine remote user is created. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server virtual machine remote user is |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmRemoteUserCreatedEventPayload](data-types/multiplayerservervmremoteusercreatedeventpayload.md)|The multiplayer server virtual machine remote user created event payload.| +|Payload|[VmRemoteUserCreatedEventPayload](data-types/vmremoteusercreatedeventpayload.md)|The multiplayer server virtual machine remote user created event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-remote-user-deleted.md b/playfab-docs/api-references/events/vm-remote-user-deleted.md similarity index 88% rename from playfab-docs/api-references/events/multiplayer-server-vm-remote-user-deleted.md rename to playfab-docs/api-references/events/vm-remote-user-deleted.md index 7040e3064..97076ab22 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-remote-user-deleted.md +++ b/playfab-docs/api-references/events/vm-remote-user-deleted.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_remote_user_deleted +title: vm_remote_user_deleted author: joannaleecy -description: multiplayer_server_vm_remote_user_deleted event. +description: vm_remote_user_deleted event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_remote_user_deleted +# vm_remote_user_deleted This event is triggered when a multiplayer server virtual machine remote user is deleted. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server virtual machine remote user is |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmRemoteUserDeletedEventPayload](data-types/multiplayerservervmremoteuserdeletedeventpayload.md)|The multiplayer server virtual machine remote user deleted event payload.| +|Payload|[VmRemoteUserDeletedEventPayload](data-types/vmremoteuserdeletedeventpayload.md)|The multiplayer server virtual machine remote user deleted event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/vm-state-change.md b/playfab-docs/api-references/events/vm-state-change.md new file mode 100644 index 000000000..049d00a4d --- /dev/null +++ b/playfab-docs/api-references/events/vm-state-change.md @@ -0,0 +1,44 @@ +--- +title: vm_state_change +author: valexao +description: vm_state_change event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# vm_state_change + +This event is triggered when a multiplayer virtual machine's state is changed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[VmStateChangeEventPayload](data-types/vmstatechangeeventpayload.md)|The multiplayer server vm state change event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-unassignment-started.md b/playfab-docs/api-references/events/vm-unassignment-started.md similarity index 88% rename from playfab-docs/api-references/events/multiplayer-server-vm-unassignment-started.md rename to playfab-docs/api-references/events/vm-unassignment-started.md index 415967b86..c51cb5bcf 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-unassignment-started.md +++ b/playfab-docs/api-references/events/vm-unassignment-started.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_unassignment_started +title: vm_unassignment_started author: joannaleecy -description: multiplayer_server_vm_unassignment_started event. +description: vm_unassignment_started event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,8 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_unassignment_started - +# vm_unassignment_started This event is triggered when a virtual machine is unassigned from a multiplayer server build. ## Properties @@ -21,7 +20,7 @@ This event is triggered when a virtual machine is unassigned from a multiplayer |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmUnassignmentStartedEventPayload](data-types/multiplayerservervmunassignmentstartedeventpayload.md)|The multiplayer server virtual machine unassignment started event payload.| +|Payload|[VmUnassignmentStartedEventPayload](data-types/vmunassignmentstartedeventpayload.md)|The multiplayer server virtual machine unassignment started event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-unhealthy.md b/playfab-docs/api-references/events/vm-unhealthy.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-vm-unhealthy.md rename to playfab-docs/api-references/events/vm-unhealthy.md index 4a0244945..b1b601daa 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-unhealthy.md +++ b/playfab-docs/api-references/events/vm-unhealthy.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_unhealthy +title: vm_unhealthy author: joannaleecy -description: multiplayer_server_vm_unhealthy event. +description: vm_unhealthy event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,8 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_unhealthy - +# vm_unhealthy This event is triggered when a virtual machine is found to be unhealthy. ## Properties @@ -21,7 +20,7 @@ This event is triggered when a virtual machine is found to be unhealthy. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmUnhealthyEventPayload](data-types/multiplayerservervmunhealthyeventpayload.md)|The multiplayer server virtual machine unassignment started event payload.| +|Payload|[VmUnhealthyEventPayload](data-types/vmunhealthyeventpayload.md)|The multiplayer server virtual machine unhealthy event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/toc.yml b/playfab-docs/api-references/toc.yml index b1afb264f..3bad324b8 100644 --- a/playfab-docs/api-references/toc.yml +++ b/playfab-docs/api-references/toc.yml @@ -111,32 +111,54 @@ href: events/matchmaking-user-ticket-completed.md - name: matchmaking_user_ticket_invite href: events/matchmaking-user-ticket-invite.md - - name: multiplayer_server_build_deleted - href: events/multiplayer-server-build-deleted.md - - name: multiplayer_server_build_region_status_changed - href: events/multiplayer-server-build-region-status-changed.md - - name: multiplayer_server_build_region_updated - href: events/multiplayer-server-build-region-updated.md - - name: multiplayer_server_certificate_deleted - href: events/multiplayer-server-certificate-deleted.md - - name: multiplayer_server_certificate_uploaded - href: events/multiplayer-server-certificate-uploaded.md - - name: multiplayer_server_create_build_initiated - href: events/multiplayer-server-create-build-initiated.md - - name: multiplayer_server_game_asset_deleted - href: events/multiplayer-server-game-asset-deleted.md - - name: multiplayer_server_requested - href: events/multiplayer-server-requested.md - - name: multiplayer_server_state_changed - href: events/multiplayer-server-state-changed.md - - name: multiplayer_server_vm_assigned - href: events/multiplayer-server-vm-assigned.md - - name: multiplayer_server_vm_remote_user_created - href: events/multiplayer-server-vm-remote-user-created.md - - name: multiplayer_server_vm_remote_user_deleted - href: events/multiplayer-server-vm-remote-user-deleted.md - - name: multiplayer_server_vm_unassignment_started - href: events/multiplayer-server-vm-unassignment-started.md + - name: build_alias_created + href: events/build-alias-created.md + - name: build_alias_deleted + href: events/build-alias-deleted.md + - name: build_alias_updated + href: events/build-alias-updated.md + - name: build_deleted + href: events/build-deleted.md + - name: build_region_status_changed + href: events/build-region-status-changed.md + - name: build_region_updated + href: events/build-region-updated.md + - name: build_region_utilization + href: events/build-region-utilization.md + - name: certificate_deleted + href: events/certificate-deleted.md + - name: certificate_uploaded + href: events/certificate-uploaded.md + - name: crash_detected + href: events/crash-detected.md + - name: create_build_initiated + href: events/create-build-initiated.md + - name: enabled_for_title + href: events/enabled-for-title.md + - name: game_asset_deleted + href: events/game-asset-deleted.md + - name: monitoring_output_saved + href: events/monitoring-output-saved.md + - name: secret_added + href: events/secret-added.md + - name: secret_deleted + href: events/secret-deleted.md + - name: server_requested + href: events/server-requested.md + - name: server_state_changed + href: events/server-state-changed.md + - name: vm_assigned + href: events/vm-assigned.md + - name: vm_game_certificates_deployed + href: events/vm-game-certificates-deployed.md + - name: vm_remote_user_created + href: events/vm-remote-user-created.md + - name: vm_remote_user_deleted + href: events/vm-remote-user-deleted.md + - name: vm_unassignment_started + href: events/vm-unassignment-started.md + - name: vm_unhealthy + href: events/vm-unhealthy.md - name: player_action_executed href: events/player-action-executed.md - name: player_ad_activity_valued From 749f39a4a2884d0fc9354ebbaa6fa0bb3a0d1806 Mon Sep 17 00:00:00 2001 From: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Date: Tue, 6 Jan 2026 17:02:26 -0600 Subject: [PATCH 02/76] Updates for OSS V1 UE5.6 release (#2765) * Updates for 5.6 release * Addressing Feedback --------- Co-authored-by: Raul Gomez Rodriguez Co-authored-by: David Kushmerick <80928711+dkushmerick@users.noreply.github.com> --- .../party-unreal-engine-oss-overview.md | 10 ++++----- .../party-unreal-engine-oss-quickstart.md | 7 ++++--- .../networking/unreal-release-notes.md | 21 +++++++++++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-overview.md b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-overview.md index 5ff7470a2..31fb0880f 100644 --- a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-overview.md +++ b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-overview.md @@ -51,11 +51,11 @@ PlayFab OSS works alongside the PlayFab SDK marketplace plugin, which provides o | 5.2 | Supported* | Supported* | Supported* | Supported* | Supported* | Supported* | | 5.3 | Supported* | Supported* | Supported* | Supported* | Supported* | Supported* | | 5.4 | Supported* | Supported* | Supported* | Supported* | Supported* | Supported* | -| 5.5 | Supported | Supported | Supported | Supported | Supported | Supported | - +| 5.5 | Supported* | Supported* | Supported* | Supported* | Supported* | Supported* | +| 5.6 | Supported | Supported | Supported | Supported | Supported | Supported | *For users on previous versions of Unreal Engine (UE4.27, 5.0, 5.1, 5.2, 5.3, and 5.4) who wish to use PlayFab Online Subsystem, here are two options: -- Upgrade your local Unreal Engine version to 5.5. +- Upgrade your local Unreal Engine version to 5.6. - Pull the latest release and backport it to your game. For UE4, 4.27 is the recommended version since crossplay between different platforms doesn't work on 4.26, but it does on 4.27. If you're on an earlier version of Unreal Engine 4, the OSS can be backported with minimal work. See [Using older versions of Unreal Engine 4](party-unreal-engine-using-older-versions.md) for more details. @@ -81,7 +81,7 @@ The supported Nintendo Switch SDK versions can be found at [Switch SDK Updates P - UE5.0: \Engine\Platforms\Switch\Source\Programs\UnrealBuildTool\SwitchPlatformSDK.cs - UE5.1, UE5.2 and UE5.3: \Engine\Platforms\Switch\Source\Programs\UnrealBuildTool\SwitchPlatformSDK.Versions.cs - UE5.4: \Engine\Platforms\Switch\Config\Switch_SDK.json -- UE5.5: \Engine\Platforms\Nintendo\Config\Nintendo_SDK.json +- UE5.5 and UE5.6: \Engine\Platforms\Nintendo\Config\Nintendo_SDK.json ## Which version of the PS5™ and PS4™ SDKs are supported? @@ -89,7 +89,7 @@ The supported Sony PlayStation SDK versions can be found at [PS4 SDK Compatibili - UE4: \Engine\Platforms\[PS4|PS5]\Source\Programs\UnrealBuildTool\UEBuild[PS4|PS5].cs - UE5.0: \Engine\Platforms\[PS4|PS5]\Source\Programs\UnrealBuildTool\[PS4|PS5]PlatformSDK.cs - UE5.1, UE5.2 and UE5.3: \Engine\Platforms\[PS4|PS5]\Source\Programs\UnrealBuildTool\[PS4|PS5]PlatformSDK.Versions.cs -- UE5.4 and UE5.5: \Engine\Platforms\[PS4|PS5]\Config\[PS4|PS5]_SDK.json +- UE5.4, UE5.5 and UE5.6: \Engine\Platforms\[PS4|PS5]\Config\[PS4|PS5]_SDK.json >[!NOTE] > In order to access Unreal’s documentation and UDN forum links above, you must be a registered Unreal Developer and tented for the specific platform. diff --git a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md index b363fa7a1..4f491b96b 100644 --- a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md +++ b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md @@ -46,7 +46,7 @@ Go to [PlayFab Online Subsystem](https://github.com/PlayFab/PlayFabMultiplayerUn { "Name": "OnlineSubsystemPlayFab", "Enabled": true, - "WhitelistPlatforms": [ + "PlatformAllowList": [ "XB1", "WinGDK", "XSX", @@ -81,6 +81,7 @@ Go to [PlayFab Online Subsystem](https://github.com/PlayFab/PlayFabMultiplayerUn * **PS5™** PS5Engine.ini * Replace the INI sections in the config if they already exist (for example, Engine.GameEngine) with the ones presented in the following sections. * Ensure you replace all the *\* fields with your data: +* On UE 5.6 and later the `DriverClassName` parameter requires the "/Script/" prefix. For example, use `"/Script/OnlineSubsystemPlayFab.PlayFabNetDriver"` instead of `"OnlineSubsystemPlayFab.PlayFabNetDriver"`. ```ini [OnlineSubsystemPlayFab] @@ -105,7 +106,7 @@ InitialConnectTimeout=30.0 [/Script/Engine.GameEngine] !NetDriverDefinitions=ClearArray -+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemPlayFab.PlayFabNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver") ++NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/OnlineSubsystemPlayFab.PlayFabNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver") ``` ## Platform Specific Considerations @@ -231,7 +232,7 @@ Ways to help you troubleshoot issues. Users might face issues when trying to create an Unreal Engine Installed Build with the OnlineSubsystemPlayFab on GDK build flavors. We provide the following guidance to successfully overcome this issue until there's a more complete solution. -**If you're using Unreal Engine 5.5 or Unreal Engine 5.4:** +**If you're using Unreal Engine 5.4, 5.5 or 5.6:** * You might encounter the following runtime error: `Runtime dependency Party.dll is configured to be staged from C:\Program Files (x86)\Microsoft GDK\\Party.dll and Engine\Plugins\Online\OnlineSubsystemPlayFab\Platforms\GDK\Redist\Party.dll` * Navigate to Engine\Platforms\GDK\Plugins\Online\OnlineSubsystemGDK\ diff --git a/playfab-docs/multiplayer/networking/unreal-release-notes.md b/playfab-docs/multiplayer/networking/unreal-release-notes.md index c6d61a2f1..04d16dc12 100644 --- a/playfab-docs/multiplayer/networking/unreal-release-notes.md +++ b/playfab-docs/multiplayer/networking/unreal-release-notes.md @@ -14,6 +14,27 @@ ms.localizationpriority: medium Refer to [QuickStart: PlayFab Online Subsystem (OSS)](party-unreal-engine-oss-quickstart.md) for download and install instructions. +## 2.3.7 +**Release 2.3.7 is ready to use with Unreal Engine 5.6.** + +**Library Updates:** + +Multiplayer SDK C++ library (Windows/GDK) : From 1.7.9 to 1.8.0. + +Party SDK C++ library (Windows/GDK) : From 1.10.5 to 1.10.12. + +**UE5.6 Upgrade Fixes:** + +### Plugin Configuration Updates + +* Updated `OnlineSubsystemPlayFab.uplugin` to use `PlatformAllowList` instead of `WhitelistPlatforms`, and renamed `OnlineSubsystemSwitch` to `OnlineSubsystemNintendo` for consistency. Also incremented the plugin version. [[1]](diffhunk://#diff-5e89106b2fe67da11c76d335b2c0f6c597035a66aa80dc7021dfc24cb8ef24cfL4-R5) [[2]](diffhunk://#diff-5e89106b2fe67da11c76d335b2c0f6c597035a66aa80dc7021dfc24cb8ef24cfL27-R27) [[3]](diffhunk://#diff-5e89106b2fe67da11c76d335b2c0f6c597035a66aa80dc7021dfc24cb8ef24cfL57-R87) +* On UE 5.6 and later the `DriverClassName` parameter requires the "/Script/" prefix. For example, use `"/Script/OnlineSubsystemPlayFab.PlayFabNetDriver"` instead of `"OnlineSubsystemPlayFab.PlayFabNetDriver"`. +Example usage: + ``` + [/Script/Engine.GameEngine] + +NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/OnlineSubsystemPlayFab.PlayFabNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver") + ``` + ## 2.3.6 **Release 2.3.6 is ready to use with Unreal Engine 5.5.** From cae84f35fde7a619e699f4810b3180754bf45419 Mon Sep 17 00:00:00 2001 From: edigonzales-microsoft Date: Mon, 12 Jan 2026 11:02:09 -0800 Subject: [PATCH 03/76] Update CODEOWNERS for playfab-docs directory to add Xbox Learning Resources team (#2762) Update CODEOWNERS for playfab-docs directory to add Xbox Learning Resources team https://github.com/orgs/MicrosoftDocs/teams/xbox-learning-resources/members --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6b7393165..f13af9242 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,4 +5,4 @@ # The '*' pattern is global owners. -/playfab-docs/ @KevinAsgari @williacj @thomasgu +/playfab-docs/ @MicrosoftDocs/xbox-learning-resources @williacj @thomasgu From 1b7e08eeca93c9da114a3ad873752c7ea974c8b4 Mon Sep 17 00:00:00 2001 From: Anthony Nguyen <108492711+antnguyen89@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:26:44 -0800 Subject: [PATCH 04/76] Xbox Title Add-on Update to enabled PC title linking (#2749) * Updating docs to include xbox live title linking. * Updating index and toc * Updating list of APIs that accept XBL tokens * Fixing doc warnings * Fixing alt text * Updating doc to reflect new UI changes --------- Co-authored-by: edigonzales-microsoft --- playfab-docs/identity/index.yml | 2 + .../platform-specific-authentication/index.md | 1 + .../xbox-add-on/Xbox-live-add-on-page.png | Bin 0 -> 233811 bytes .../partner-center-configuration-page.png | Bin 0 -> 42454 bytes .../xbox-add-on/partner-center-product-id.png | Bin 0 -> 104525 bytes .../xbox-add-on-installation-validation.png | Bin 0 -> 59662 bytes .../xbox-add-on/xbox-add-on-installation.png | Bin 0 -> 71899 bytes .../platform-specific-authentication/toc.yml | 2 + .../xbox-live-add-on.md | 64 ++++++++++++++++++ 9 files changed, 69 insertions(+) create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/Xbox-live-add-on-page.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/partner-center-configuration-page.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/partner-center-product-id.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/xbox-add-on-installation-validation.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/xbox-add-on-installation.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md diff --git a/playfab-docs/identity/index.yml b/playfab-docs/identity/index.yml index 871e72c9f..9f390886d 100644 --- a/playfab-docs/identity/index.yml +++ b/playfab-docs/identity/index.yml @@ -52,6 +52,8 @@ landingContent: url: player-identity/platform-specific-authentication/google-sign-in-unity.md - text: Setup Sign In with Apple for PlayFab url: player-identity/platform-specific-authentication/apple-open-id.md + - text: Setting up Xbox Live title association in PlayFab + url: player-identity/platform-specific-authentication/xbox-live-add-on.md - text: Running an HTTP server for testing url: player-identity/platform-specific-authentication/running-an-http-server-for-testing.md diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/index.md b/playfab-docs/identity/player-identity/platform-specific-authentication/index.md index 1fdcb122a..a445584bc 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/index.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/index.md @@ -59,6 +59,7 @@ If you're unable to access the above secure link, see [Request access](https://a ### Windows and Xbox +- [Setting up Xbox Live title association in PlayFab](xbox-live-add-on.md) - [Authenticate Xbox Live users using PlayFab's Xbox Live Helper Library (recommended)](../../../multiplayer/networking/party-xbox-live-guide.md#mapping-between-xbox-live-user-ids-and-playfab-entity-ids) - [Setting up PlayFab authentication using Universal Windows Platform](uwp.md) - [Integrating the Universal Windows Platform with PlayFab](uwp-integration.md) diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/Xbox-live-add-on-page.png b/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/Xbox-live-add-on-page.png new file mode 100644 index 0000000000000000000000000000000000000000..602cb51922dfd4f5cc22f1b4862d664c3ed25152 GIT binary patch literal 233811 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
v?7rUU*}eV2dWp}3e>TnS{vVUU-l_iH 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

xpAF3 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 X_T^MaOTFc>*Kk8i|7zKlI}!g2j&ja^ literal 0 HcmV?d00001 diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/partner-center-configuration-page.png b/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/partner-center-configuration-page.png new file mode 100644 index 0000000000000000000000000000000000000000..d6dc1167811c17667536f13edd9181f4360e3cea GIT binary patch literal 42454 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 TbGNR$b!pY`hRw@LH;2!1ihZ~ZZ|_BzHLsc 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 literal 0 HcmV?d00001 diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/xbox-add-on-installation-validation.png b/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/xbox-add-on-installation-validation.png new file mode 100644 index 0000000000000000000000000000000000000000..9bb590e0305d72107ed933da71029d3c0b997c4f GIT binary patch literal 59662 zcmeFYXHb(})HW)LAYDX7lp>&Dqezt+nt&o;p|{Wx2));+RA~W`4kBH8P3Q?tKzeTh zqS8wUHGzaAA3p7!Gjo2NfA5@`@19B9bLZZBuf6tK>$=w3A75&zG0@(mJ$LRL!!vc2 z*XPb%K%P5yKJF6LSqrR{_R-k~rJbUt;<Fh7-pPs2G>iC*%6Tv#xU^A{`0tN?> zqvp936@2@5Tj5+1LlA7f92Duw=q9x@)%QhN2@@V_{qTJ%(-rNd;u*zE`*1yg_e;gO zy1~FiRZCSxv;uuX`oPQ`s~(4%KQ&AOC5NvB>!Q+qa>A8`pJ$ zR!V{GtW1c=;S>M_Ks*3^?-y$6YOY*-x_9vOC?4GJkxlHd+p}8%bY_E3hWC;xgT7}D z+=~78Sz7bcyW-cX0J!hNzkU>D|Lh@kLVg91zvF((fblYWU$}yp;2U_!9KQ-fIU^J@ zYKRNnwUXTugE1s>nh<=ZcSixo_nreE{fY*Xc;I+wWqKlbNf^Y!{O20|=%$1%0^sah zaMP%0vfBo@OY*c=@~Z_br?6+5ygR)l;~Y%ANSdsFB=m7t&YLN1h;WTpCZ}j0MbpJ6}(EgbnjPT>zdoA20W7|8@it(xv(( z&v#1v)jM-mq!33i4cE!C+HQ^=S4X8BQM`;a^#G1ZK`^BR|Gr|hh_t+j;fiBid|*Bt z)JnU7@?SFEt0y0!y8G1hcU|O3F7W}$Z6Q3Rp@Z>bSm zKVh(ygQS_|pyNnAU3qqG3K+DJB$Xz4^WQ;C#vYDV6xi3tsFL2J@b7NkLkpem0$*wl zumBR;AmHVmz2dQ=fqJ!1epAwz#IAp*@3m)6rYOW{E)`*eX$jd2mHy{MX?n-lPl58M zDaSurv%9#!BuFXa;66O1(yXM7M8v_l5c|!D*GG2RSN`psBYNT<06)Qd`aKNs&7r7( zreVHsD|_ek&9%@{2E>)2l~-tjjmmx!xh{A0q2{Q~;us>}V9$0^k(~eE8YVmwPF`Jf zHx~4$5@kDw77`-a1bUM5o}6yxoQ(1&-WI4Q<9D(N&SGSB4|6ywkeIP&OpQ1)x*+-A zDAMMY3FHO>SY>fY!yyA?+Gcw79Hp@2 zmc{>+T-{p7t?^pQgn5RAK3IM5KoX9*wMSxVCtOF1mwU^`o_%8}0vHrcSP@8kmVbY1+;1At9^`xeQY|K}* zzwy^u-wEYaTs9L)6uu9wOih$=qeuR&kvgLG@}vvoRq6**!Wm37ZGinPK(0JcU;`6` zS;FlO9-!D$%?f(R*!N@x;PDviz_Tw;!kzxo8lIAm6Ar8ZpibVqj9;*^JVH)QWs{_`#2)mF;lTrcAHXjlyE8PLg zF$OSE!q*em>n|1>Z|s4IrQ}k(~JC6-%kg=L?vj?~ZU8ea#DG8{7oVW7-vz;>LoAFHY2h=4PD4W9)=LLYwJ0D}RSRB3 zn!ZN+x*jq9N{yLhTddvPHj%$AUILm9NIFj%1|NZ`IzSW3RQHStXlN9%u7In7-Wuzu z4KBC5mweNqu|QwoLfujMVb08{L8jxX=FbHGlJ1m zK)TS`Z$0b7kl!A_Qxg!_zA*wuxsPZ$PSF)OhL9q-%6)~L*><;snlYWz!$CpjUo0RM zTw5LeLZKIP6Wz9}1SkR?j(!{G zun+K6vlj~wziv~mbc)d83P;DKLv31BIqq(2@s0TOUurMVjPZP7-k<4xqZLaOhNMNV zF2Ay9c6GcYus}L`2rzuw#A_`qm8P%$F6k%x)Om$3E|_)tv`WfD3G$)i1IYkGk!S-> z_Kwq#pZM@_r)Hph$X{+`^gGXm*r1+4%%#xTsvfY<0iu(iw9Hane}W$ekl&mhM}XP0 zB&8Qd2mi8b*h+XT8E;3P3~bhL24MLsNt8qYk}K6^ChtToeXj?M?OCZ-^~V|G!HnixM5 z9dh5Ke^L(R!D%=Z{Ai2oBQ3Jz5eq5$%9S=ht5(NG!xui*Hn{YjcG9FW(}Nw8QU z5K`b$@{PK`td$^7u_kGC3&nn^W_1ZnY$KPbGD2wkL_``V%)keMhjm7%=_m}56%`FQ z-sVyXx30ChzV^uDf;W8_MaW+slI$ohDqT?OANNnDW zE0rFSkqS7jS4fk_abPH8%>>C6YJAs|gty;P>VSD@yR~}DJ_7aEgkqt3Wzo!Vn^=0} z>;CLrO@wd2B{|75SL24!=ys%8Yh8KixNyZz(?Rr$%YsMFb~kOJZ&7un33!LOA=6r?eec+*tKuUNj_BJYEKiJY!Q zzU@IDyzmm~M&?mcHOvYW#f4jyXGA9Kc5!_ zx7z}(Xnfr;Oj`ll^Hlwe--n!j+|!RH&kw0scriv!k|)xxrC?k4ccLe_IFu{ zyq_KWGV<1&;1RJ8jab|x#O@+$J`$!`xQShmm(EF3GM8cK1XQQ9z3N|bTuYy4A@t#s z6jHs;mrrnJ1eMxcu0=9Amm2%0Wfvcf;urM-$(6x?=U~nOS)lAG4}5FN=b}6>gnVL0 zvh&LMS;zhugcQ$s6_WD|y=B=4h^n6u(H6R$$lkqgHtMJ)h?|8!4o&Xo4oQ!B4MxuVfh<&BLhNH1CNapNL*;oOh{O{ko%n-nS7nkcwvT1BOf?7u*xcZ3!;%FD6zDc z;6U#09X{e|yb)9I9GX-0di`p|#rYTFVc|}%{Hvk{6wV9mw7qp&f6i#-U3+=G(rhk6 z85mJ-R?9UCgi@J`X2i?n&-$B)9&Yvx>e;vEb-?7V1Stz>9{s&RUnD9JKBi>93`yRw z(4&$ioIxeL19Sy-1{Vz`eaT^5B)a$K0y86GeBlQKnfIXBT>vlOSZtmJ|EKm-8@W*r2KZNo7xWyIJwPD+CRf`o5;uS19%!$CLE z7#DpDz4Oos_U1}3+OZ@X`^tGwcT3rs2AdcF*f>)w&4mDPjlMXS%NNIPHTjc-5$3V~ zK}?e`R7s==#3_@m2O5DF1yADU`t^l$5gY!vamE03bkiX!c@DIIMC`*#+{jyJ*r#~f zf$qOBKW&1OD-f%2lrePrx;x0sp%rx!>!TA}%NC=($vyakJSB805V+!KhK9xH35su3 z=INcO?>}HUp?7^T8prD9wN*lxKSS`}>jeWH7n~1t(aPyH53z8^6m^ z1v(vYi*Jz85OV#Fd*HABB9yjq&wt?aAPYdua=7X$N}t`Wtjd`Z@D4%qZ+G9E!^tbV zj-|7~!w`6n4_(#t$A3H6T>Zr*uakqTqgE$$T|PTDiuoTi3FW%rS`VVq`+={r~!@xZ?^YX=L{VfQhZge>wQxqchyrLT>K{ zwEaQ9sBd2d{=Iu$C2->*u%i~>7mhfh18ayMNObPM;<{3UusaIa9VJ3?0}XTyw> z|4x!$)gcpcydw0QMF{Y|7?{=JGk?nHr415Q(D(2C>Nv(~@_`T%LVetk0)JN-h#tH_ zFF^k08`Z@*kMfUuVRJ-Y?Z5{UQ6?mkEv z-unnRp_JFfUtJ73s-T_DCj4I0X(R3H!$DfBvEBbZz=d)nfXIhM$kYC-i@DNP|KLZS z64C$Lct+j)ZwRDzDGV(n+leD~LViyp%;7&zdiNu$@%Il5&t>B|@>2lz@&x>6oU4am z#HW+fgtK^eJo=<)_23J!;HrqsYAsL13x|t@)$yJ?2afA!f%PZZ*XpR=9M8A#e$RKO zA-N~{Iiax|Qu9I=eBmFKt%m|H{2kASd6ZR|E)wp+3Dkg43^FnQ+Ri|z)2luU?40*C z?z#^}bn9CiPf@WSPNKHFLY-WKZLVG?j3x~dP}ctN4+Cec07&d#rCGUQ(HsK=o(k)M zw|wH^Cj{3etUl_y(88%Od}}jecL9KvF=*KcLk|;&T&$MQT1)}Q7N;XZ%e)=f>?KL^ zcb9L&WNq>p9WaVI@z~nXCNg#hZ`M~I!zRHzrD#b~kG{RHn{HeKlb;pm{gL4ORIoLG=t=S8VTQNp5zh|2#O$y7 znAqyiIC$$LqmB+3=HM>K2ESmt*_^0(!?6B>w><~%hF5AVBE;g>OkaN0>3qdUM3bGI zUuqBN0iEue(-g>YW$zgO?a1(-<;;D@8-eyA6J35b2e+3zCA9*NFL#rOYZC~rpr6X# zm#*7@q{NZgM7fw&GH$oxV2nTb7V6p+7}#ZjW;9vbIq(MHP&?q1kIesB6A_NbAoBfSQjp9sEC%a~!j#-bGa-TBE6F-4Go(&byN`yiAW1%Worri} zjU!X(1!L}6AYTWc*q@H|MLgbrxWgW|`b69%YCMZ~{af>>Q92F2-&}=ZNaSIWq7G-565lI^B~Bz3V|_| z78cPlB|^hsFR+YYH`s>+EWKDmX|g+KTUhE-u6)gO@89;!Eod|QcsCa83D74Yb% zZIt*w?BuJstFXK4>Adk8y_`tW_|G$l6KOPa&K_YvIA{OMf&i&Xg;J>zDoPQ*S`m6j z4M)>Ml%G~FEjxqXlF!*o))EsgfH*rPrr)L0t!BNuYz}BCbSwIKmA)4)wR9AzgoMe zwCd#!@TZ<>fW`H!j`No_$j5}Qx`A3nfW@!QSTHq~In)q0s9zSo7#%)E14>%1loVK& zBK#7bGE1$TJ!39MQakoN4#FH-zBn1rX23Wi*B=!h1~ec(D=9BgdJnQ{8LngIUk%Zi zB|cwyp`x;e-0Q?1^F@8nJ@RdeC}()Ms{3%|nGo+&83FiQSB1k`z;t`9G@NO+@@632_ou~6`G3nY)TAON> zz5(m8Pwq>7xgt>^mXl*g0b$Boi!#uV%=y*F*HV657$)loU{A|bXvXBeTRju*-~!BL z&ii(5ZT=YMSH=}s$fl2$>&*vAqRh-$F8o(vVMPDo^YeJ8=47$jyjJvg3ET13x1;Gf z{No-oNqp_!ovfQeG$*r$OSvAWf$u|BszZw2~Lf{V}^C2Yd8qr;n~IWg<) zdTLv8HGqYAg9p3>vOow$on$PGLI%(+K8jN(vGZ7PSy{05vVl__AWB*u8QA~oS7zI= zJoRJN<)owLD{pDMZn(cFud9eUk}?b*>%10YTC=!y>KvBjVXr30=)+Tse(~c}^Q{u0 zAlQ0Go<@r4HcxKtGG(X4%NCh!GPC%F-BR|#{L01n$ZkXzU7Ph)0)UrFDbSgJ>lb-i-rn+k|#HB2B1$ke(vGLJ`MiK&aeSy zI7=nGuHLdea3$Qa*o8ska`=@4Jk~Xae`)Q|U~PhNH4l0vV#303w;eMWtk4@0BIRbg zSOfm+CG3gg4Ym3&kxsbodrixf?d!N!u!hkSF>a~WD1vtM47e`#gqfy*q{lQxz*lcm z88jElK_iva-{A}hIns&`4EyIl&0frM_OA#iFT{l$n$>0& z^}@LkFH?+$0c@(X)%SJx4zfo3j_~j8+JMs3*QP>;NA>kC?u-XkPV0V1K|~QXwkeH2 zT+8taSu8TLLxt2ms{{sqF=ka=up+m!fTVhYagv&GVVZA$tU{TLdfKfYTx*Cg6MXG0 zq!JhX%Q%j9jgn6sJ@qJ1gC_@&q%?LK8+68EcT=u%&4Trz6&=#oA%g<9XXRo}0``%{ z3hi)Thh&e9Umwz)QJ;L6XYoXjA(mwykq8+{)yLNZa?&Crhd!_{AbT|lmC_j$21Jga zr^qXET>P?I03$&UvmF9bxV8xK>cjK{D(K~h16=C*y`IY2&%4Gi9*V*2^(zHd2HlQ2 zrO6Yxx}F^u=c#iB;uks%YO~`qD|6;>hKyCR<`En3hjeyo84cpT49mKH-Zoyy9Nq)A;Az?3 z78%1mYj(j+wbEF%x~GmQSI_Y)r8jfQe@w0Svs~MaKzDrds*$K=4diD|xW6wsbX^uZ z+oK88=Z*H7KMEfAMoAQwJH)ED z^4I}R@c^W^CvR*qO6&K-M@i6fhW|Rrh%TemjCY9Ug^GtGM!fvG;*-IdN+BcYrUmP( z^QRU_0shtkrQ0B5iYEq+LITYB_nYb=DoNFbxAKfAd$F%=z7F<(6L2fE6TgV7H9K%H zE<@xAs`^Q3gvSi%}qm_DWVI2JXOGQ&qX49C5L4b}}FerD8g)Q=FZ_DpR7q~46O`GPt zYu)yG!o2>BIc{;R`L&av(2?OH?+sC+>%i z7X53q_th*WZ~BVQC#6{!JM!$9To&$x$+>t0geK`OOZWcBL-w`N9#4rp3F>X31DzqF`@xYvtHYOSAE(nIJk z9$)jXN;+v`bqwkmb!}fVKa)ee7YI8%3|A29F~-e+OetN3-c8q3R3koWNon8CGm2rb z5-79$RTaA6h;3jmC-y#Cc`4kSa8_=T=9z1O#3yX`)EwNpdT>E6nD0V>p?C>Hi2q2` z7j2L$O`85ZVQ_i?VfvS@7(B=t`20Kg1ru%pf*7w`*wjE*erFoMDeA@cmg7^4<&oGH z`Frhh4S|Z@2hO^AJK|f|6vg?E-}gFUZ%Uo9IgsmDU^a^-y6=M?it0AA(<808=$%=% zUX{%Iw^b~>w8DIwV{yTkOd%_{XZwzE3%$hW?A#y?Lxwm8HAt71%2gh$!By|mk56ok z2T=BehBAlna{2k8HJ$SMg$L>!7^`GO%4A;QO5e=`Y+Lc>%yys_M?G3kZ8+aAU{^A? z$t#wiIU(4@6vr!Y;p@rHj>SFJJ>MY45QobRl!Y@!A0yWXWE!i`hl(5~N9jsEq<4mW z+N|a6%JY2i(Swh2hL_S(j`CQ?%8XaJ^|MOtRVzLids!g;fRoySWkOJv38FT&0d8&wr}bolCUSOufzi)}x}KV`jP%wyQLY(bQsph1%XY%s z3?Z~S4XB9K)6p^^cO;VJeTJ=pBU<^Huk1S0FWnpv!M+ves}aPX1305U>Kf-tCV1j6 zhND@gS_W*FEe@`Gzv-4LPN`PohOCRKt5`>!#@1eh0I2N&tXL?#ewKL_pSC5^?XZpxujqVhq)KRycpk;Kgams+k1@``F3pJ0MbWC`j3RJ!IY`gYf)Rb zZfkxhC0-~F2sFj(g+-th-qlcdK1VTe;|b{+T7 zGd_AAHspBWp+P_FgiuwQSS>M7*8iQl+$Q3i-@CeRXxq%69M{XD>E0`%A|pRof&t19 z0F?gbs>#c&?sU;FVT2D}16n9k{rBDvmai(Yn#8Spe0b^oJ>QAOB{VDJ+)jv z?nBX->{ZTlMh}1(Y}wqHjp_wfSW#VHA|n?Adzg@OXi3@t8+DVe3E0u;&Z&9f&i8qjJL$|I|=7T@h8BiO!l0%9& z2HOzZ=bS$+h{JQ88}pN$q{EW?TOT|+5xgOrSzDoJ=P@OgeRaO=(10Ou>|?v*RC&fS zmb-ZqYrE9IBE6e5bdw{%_3gboD%9FaWx)suBs(*TVJ%s##_}=y zPm(9gjmn7n&h+T=yAfCpi(dT%Y zde3B@7YD%J1}3>gtaw#E;~SiMg{@2Eu1C=_!`NS~QU2OS#{JlvX{m=vYgZ*d7FIW& z+`8%hXo|9Lwo$l*xQMnb$j0({PYS$TNzS6vOZ4#Y`?Fc4f@dVCQXDq4xPzSJ0zKVC z&msDj3LmHH2e`BMGsS#+*=ObV;(WTUXcp<+QQq}q=JB)x_w(_mw{MPbu^B7M-^sdK zUo^@O@Wm3&KvsefTVC;lyUQuvqc)Xl{ktWw7dG3dj6b2Zz81&*{G#c-hK^_9RjT)$ zl!jx?YioZ#i-fYvZCXZ5$m1+Q_aUDg7CElXz1#ny8@=rq_O&`aMdp`*)}ykYM*a=I z8J*XL`cJC@N$s@Vbw@5-scl&ii!!`wQDmP3I22@Y!!6>J8P2Rr^GFgz1J?;CJxd@T@vk6q=f1tQLX1 z9(6_?w(VJ-v8uYE7>daVbc4HJUTP1s6_L2*HefaNIO{ATO|Bm1v`sYJPA*48$wo z34bu&XlMUaZnzxeQlhoDv%8V0b5@um8?S)JvV6`O(U({Fm1+U|(vP7lyJtn-xo0%C zbwuOd!-(`7$j{TBxL{$NJzaW!s#|(gK8=o8F;PqZuteHb=N4?Ke zE9qJb8CZp7l(i#Nh()zuXWH?OJCEp;8uN_PuFa|-ep1b#@(PhU~DcVP_L4~&>-(XzrxvLd0}2MzJ`k-B88{{xSTIa>}9sZwg0V zn!0+%ix(o;3MUTn)n(VqV@@-51Lha!LX+WA%jgwk)(eZ1oQWOvlNU=V68t0M55%*l zng)Zr(s8|LrvdEU?YTAXN6r0CDUcVjGCjIr@KAb-$oCh3Aq zx774~&I=4W-Dt5f1>FySgqXOqfS9T*9A8Xt>ovu6#59stKf(YYO@VS?XFsmJc?Po*f_Z^xa)0l()oT(4Fy1k-p|rtv>I&udT%Q|vwLvk^IXrZbe3L_L&`p5 z^i1kD6k_VM-VC$j5YmvcZX%9vYz_T}>jwqr{*{0gynJm=P}^$DaQ8)?YaZ(lAKIxO zK>J&1jBAun0d4~3aQ?6i?egIi82`x5gc;mGt;y=Vu@IUj8SS_I;#fIV)nRVjrd$6OdXL7tgr1`HM=0 zUN;=Q6EgaNi|lFvwnzt&a)&hOg=kTWt;&OoQ=KB5LfB@CM^(WQegmGq1ZFd5f>z|g ztd>iVPI>T~vk*Dcxe+A!Y>=Df%|pGj8Ww^Bs{Cg#C^;vvXI?~wE$n-+=Pc4tzeO(e z%PlkE*T@mG@croXQP>CDsGCaB2PbEwRUq)W49i=W!w&D|!}BXw4v14N6&RX1 z`%e<8&@$#(Q9n~s%!(3cIQbtBK974m-1bo+E9>xZICQgKTQOMJcxBUR%I65WI0UMF ztbb(leA4d??&EJP`&deTxb=+#DSj!r_Lj___I6(#PU=^HbMU>l6sB+%-7RRjGL1vt z+_M(G9ZD^S11f!V;uO2cAj?c_>eN{^-J1s&F5+|#@)u6aAfd(Gd|RVu{(1Sq{?M}` zML|H zzhN{WysED`6DN%**9m_zui9Pl3+GoIrHJE!l!dUe2Oh3`yo9`BdrE+8voH_#25s4W z*7$nbf~g;N#4mE*2kAF!@s(%(hEI=8%%V({u}f;5{}l_m|--;e8Yq;{bFyr`KF;5=u1=faQC>0KMd)q93863rHWt+X5 z=(Ai^&iIWv#9W0Vrldd{>1UvMIhPXA@+!(lEdkCU|2gzNY>7-GB^sjBRT3PagSk^^ z*wZdPKymjx|9R+xCDLRlnYO9KqKZkj=S%R#O%)wScPmlt2fQ3^<}q_RjX}%Q)#A~F zq+p$`pPCGMZgDNc(;YKh4pNK}k0FD&wb!Xq-%BT;zT>!$`-!^wGMVWbvn21AW1Lf% zMwrXG;$)BkzfS^!T+Q$LnqV10UmV-qRP==*BU%4Td(fn;y(D0Zg}Lx^Cl9QUP`;WD z7rBJ`vg-EuiHi{Bw}T9YS;H;n)68t2U%W2{V00&~F9+L|J7L#02REMBT!WFC8oVyG zT(4nh!BN(`SpU?itKtwbjb`gU4eV!q9J^58DI`JJKSJNgy_I*>&2Gf`x!~4vsJ^{> zvshfdn7#x|QD=tnbES)vWuaZN#sCh9ISOW-xcc&H1kU+!}@18bafw_c& z&-iO|qnbqvLdYO7xTnm=H3($OMqn2QMU?xv0(T8C2tS!Egu&%A8ls2(fXK8qBDfGX zun(~4p+zos?=pR0ZloyHA*?CW9?$%iA!XBhxJJ}&-huTzdogaE3}!eGqy8+6_^FnY zP7!C>S>gGqbn4k!iGy4rml`8Xzg8V`LZHSoeHo3D6;{W_s^pDZKe*9$RJA zMohJIO~(Ilgl5)d@Ygfi_aSq|4`Spt7^DQL*3em>`=w7Ddc@j?PoA+sU#L#@c7dAX zt;{`Vl5c(sm3)%G4I+BEZC&;ic)4{QSR0FOs4{KSECRcKO&+xfe+)qFhoQMjvfZnO zVV9CEj-bAq^+6j7npS7b@x<6?1UEGDLv3}Qpx9e7V=%5oUtV}&TcPQDp(5*(beL1~xjIGR`DwG2$1=CGh%&lGM0jJ%VO&R+;*z;w zc74VeWg!}_#{W#7iq z3dJjwkKF^tKZi7vt?xeRjr6NZxsXKaybsix zywfA69+rd8kB-7EBMW*L@}7+gwtYlz9upKS7xTIS|4G9)hMG}RDn=TDiF7$fJko=!<& z2s}G!;v7#e#eT!!lG~WR=H`C_DVXsLJEW9d*Xu5H;G&EKY44zdYbu5m+=ip)@Jk9 zq!#3)h&%FoR!qbr1b$&uP(mH$XvcZx?W2t&emas!`6by75%ngxN(bZ_uLylOhw*je z*f`5CN&%b#3=f}(C)twq4TF8SIKLZpX{{T}dysw8diGuU=Xlez({0wbaLzbwUBn7L zg1ttt_>nDD>({T{y1gLBAZ?k4;Z8>!V}1Fju0sNeGaG3uSI%lBTH`R~!R(JaVJ-wc zzk#u?q&Kd!br>k#X?kjFMOw9Fr&hotnk+~O_n8bwHyp{2RnO5QX$IuQP*zg=J{|I^ zMuh0rOcAZn)AE|aS-`@U|F2v19gD$35^pHXg1`k*e*CHuozuH_Cip=S^dEkqVN!Qmo9H#Vni!9}#9eUQ$PD{0b^z7|+QOfqHd?p?r?z8_@bd5!7MzQx= zMsK^?vcjxfM9a~KO_rYn#)F+Vwz(a4FQQoWKXT5Pll1_qQ&}7ZF_xqA_RF+!-Xr%} zf3@6om;0TpiT?Sg02lEM|GLgk@kIsa2`u7`H?%@|!rgIP2T(KjUT#@o2`mUnYj=xb zkj_rx;er#*OXzD|)7Me*=_*?aa+KR$znBiat3iaY}>3|3!b zOQ=4&YKd7JJtN$x}$`@u$doI>&|nGr(pW!^abgpj_jZB~mO<~Q^2w0>C_Pr!!NxMY3< z){tBSR)M`t@GGx^EqZK&IF_i?KLS<>-?`{`;mB2ac2V`Atv6lW4GYArPbOj;&>gPr z7La64a`ZL#_Tr~huisqE=bE-@cCsqb77RCFweeqE^zI+!a56R>sp@$ak6LM$sPpVE zFI5Ug6|7p7-G4d$`ix*Peb*!wCo}gfPcoa*zgw@$dk{IyGtA3wn>v={p8AQj?LLYd z6NBye38b7y@vjjVoHoyoybuH}k}zq_TANBBe*E?F=-Bq*u=o+lsZzoHC%9Sf=GmuC z&G9I8IZ#GFMyw!-mNHFELk-|OH?6EZ4P>cj%&BZ7BzQ0bWl~1fcriCRPVt$n!gbFX z8`mc#TVq$;oU$_MQWo5+oiF)p&l)ZH+!+x!`Tll!Cr7>T$|b$J)w@Kq=xqqSHyxxE`d+mKIM{UtzleeQG;cs0@@i z@mV&fe$Ucmen1I5&>$B>UJ!!o2K_<>A|CE^Nsg3t8QD3Shq#H+Kl%wbQ~qVeagI=d zY2=SdPCXJ%8%z$=l#B^6Fb|j^SNL({CL3qNTY8#PufP%Znwy*gx6=mCB6q{``}rGD zwSw0=VPM3kn|mW6b_O%@9q+DLJm1QD`}Rv)ve~Vhsqm@Ke8NFskNmSOFam3({KOf+ zm0Sax0?gb|ccN~--Vu;}VAgy$I$g$=)evC7R& zj-NwGFbdXJ-cM|i+%ao*Tj9iptdC()k%~4SwlHYcYY<*4q71V^VS|;{wmg^5b|fLQ z5pbL$v}u4Y0+R==YTafT!u%_3^brrn?<(ufBMhu$fP63T^ z*LPa5q3(@*-h7iFB{PUo_xh6V@mCQy!c%iXngiQNvE@wM+}ctchg&usiYph=nY_L) z3K_&pQ>7@QY}@_PwlLpT4BiIT#|AxlNxG^f81=S(ktbL59m+U2O6v)z|C!A#5nQIf z|B{M6e#T@$S@G7@4zgeDL}>rzUFSDfMdvxnZDsIX{jxdHY=J6Mp2aBX`=A~AL*|J! zX31lvpIt(><`+y)e(-$a@EC=uxu^sKEkM>dqHnq zr){!u?{>7HozBy=;IF7}Z#uaEBdWR~DybGoMiQFCX$RlKkjuN0&lHoBu2FOtd?3=w z9TRitu)>Cze?PL09L}!X?2Ld-BantzbBf5aJS~ga@Tq^$Yoerf{(h6t6$5+~9;c%3R+>p*N|2aGw=c zA7DZ|VGDkXY-JYyw~X~8f;6A3boEN!QyHk6Y@;3&kp}TorMMe-yO2LA^GQWO@3PU< z!$y0Tv|7${kn^axUUA@MpaCI8^AvXH4^W?rTafk;LU7z8uS9n{~QQZ`O`7F6Op>S)G@e1=5*yN=I_|MC7ky@_i^a1B? z1f`eE*1dXj6FQ&N0UO|!jP)*#6%+Em2zxqko8vw1=CYSKZJ=)>K?%6L_dJy80SgpJ z8OK|gN|813jf@p*7KB)xR6Oo|DL@FEsLmT(dq98tnuNNB$w^v|Eeg&ouJHV=RCok> zE-s9O@jeP!zI>L!_B+G;rb4f`eoJh~w)%t7adX-hGi+ZP1(i&rb%#49`lN$=MqwVt+iNc?jz z&g{*Md|Q@9Bf|PY{>cH`9h}Ems51U}H6$hCaV6^Er%eYkw#wmr<^)wPuk^JZ1|+*q z_&USoZS3W{GeKcP1xuXB;hOa6Ry+nGI1{^esiUc3Qg?sqm_^T2)w^nV( z-JG%J+s=pI3*5I&j>J7C!=2dL;pw>1jgJd_Om&KPo@QyE4uAgdY5B{K6Dw>8t%BX| zQ~!+muVfEvtruFO6_#tBHh?E@SnE;^v7100wEx1W zTb2t2`7T<{g7gddKzmXE)Dmh zrgRCKq*?nzVkgS5-zjS@o{##L^${t*;9=1G(8v1Ox8^`k&9!-Fy^DTkQ$@5U1z?Mt2TjX17Geo-J&)wwz|CM}Y(9HjZSL2Sp1 z|C7C@bDpb@&ccSpOSH_jKHI>Hj*0FXT3bUmtbCwEJ_jI82BemAb1JO+`$L*~E8DGv zZy4><;B|tQtg#}n-lM6gwk&anGH}>x5jY8Do#r z6FOtHE1W}ETR{mixA`@D$9=NGqn>U9JXW(hbxK8D?NtnfQ}oZj$9PA)8W(l;vZJIc zws0B-{U7GuGpxxi>>5fk*+yvKtv=_bi0r=97}~|IC)z zjx1cP4`!?B*A=F5KA^7>S~V^9a&5)l$|t|#Ju5>*mF^cZS2L2{bbV+vij3)mUAK|n z^Z(VX!2RXXn_mYX*CLE|6^vVE3ut|@kH)-4bzp_~eRX-_5+b7EdZ{~|w#HAtqqf*` zpQ5JiCzLM0h@033G}KN7R>ss|5NcFz9o!U7G6sYu(ofAZLIyj-&Q3&0*`s6U(e!KP zBd2!IE;OaxckG&V@asRi)p5Z>YtV#fW5fBv!P^TYWI-IPvUFWvH|^8qQ#6!Fl5>7IGWtUv{$dno}A7H~naw_7 zsEv25akjFZ!ZQCDgK1B5`Mfi5r2KNe#$~QG*2BY>n#E%5`|>s1V~n6^;AU);Gb2;u zJb&_%n}Qwu(GNGuAeL`dFHs}x-mI~T;+EtaM&cl)sAVUu+xE)ldP7ClkrkqD;YfOz z)F^*wPtea`^lh2R`*dla!JR#3dvlXclh2BM)pl^L=2D#4 zTIW~X9;foUZwO3vo)jb%^^X7%rD&v~v>rJUSew_~EAp#89rR8rMGS+Mg@tLzpAh%_ zA|gl~qdJRNTLos%vt_mlci!qS676dl`<^W^{R|hay?O3jlUc;|@2*cFLAnlY}3Ojr7c+~Tl~5Kx1v-1c0vg=F_jIK z{?ur*_#cd7@~H0yi*!?+1v6nsE5p9iFUEYH+Vw`YiTOE-VZ8SOdLYs6AeSywdcCH{ckXD0pktBX+&XD%-hxnaDS^am#EZOI?T8mdF!J(_Qp__$$JHaIa6d%h~4 zUyHa~5<;FA@w8i{)5Jn0r7gQVg5Q41-mEcC5ZLp$K64q;d(PvlwfWtY8P{FXmdYQ( zG<)$)%tQK^=5Ucv*Kz*1U6b*T6-e6h&~QncHRR@MzufMnkzg{SrOSv8QR~kJ{3|%K1r<_@4jFDeQqtkW^BR;MH-_1*Ejz_piPG ztX+OC;fGGqI4Xq>N(`|TPqm$u&5fZY>XCA;q5_kP#o~4;MP(zCCkyqI$5|wZW=ub* z&rHs&=a90^4|0f)_Qwl9_i4wAwxF}g!H!HkeVWXtpY;Qou_Kqq31>_t2PdXrPAQW3 zeYzPzLwR%Q@+*n-1DHBEkEqB0)Z`*h>PVuyc2V0c zosFa1VgNeCWbPBcf9*Tn45_@ix6FXDp|TTJVw)zQ$ye$cQLh0+Hxm5tdJ|TBa}(6N1|#?&u)>(?eRx^@o3XqvD2B>=`c+6 z{uK=5`@Vm$0leSmJMO$#&Ijr;yRj_A%*q&E#VJ%$a+`l&pX`KEY?jnA;1m869kc;0 z1tV`q@=dZuEJ=@_=RoTRW^qWt`(+L3P;|wFynfJ~1!9NSf#;M(4s_E*%7gv&sb@9z zRjJE^)RT)&bLKQL+6e#q>EKGZClGqD8Yv@Yglc=g#=gRl+zdZv)!>?<=EQeozl|;Q zq?Pvj6d9jv+4!NrH*--+P1-8P61{p#)%_!iqw(u|N%c=SMO8+k#J26Nj5LSfQSq!g z`Ew^X-=@^_qy`7{(&%}O?>ZVJ$cvGT&0Wn}1mMdOl*lLhVxy8A<}(bQ8RyRpI_m-! zw5IgkU$NP!(vwoor*@?^7XhJLCc%E_E#%?}`}+c!ZhONhSfeN6?!1VanjG>(hNtBubZ#{3 zUjNt`LWSQ7+nw=CLxD9~Msr=KKLFoAfH8FE>!}WecC5&w9&8Yz0DhlemMwZ>qONMt zh}7lqX$WEAcbE5{)UTK~XE72Eq~PVNF_j#xJ6f;EX-?hu`pi|N^%1uUF3uj8%$%R+ zrrZbjj_0W3WMUzH8Jl#^PDl1;?1Vwl zQ4K$IX|Y42sBU|(Q#Slov;4vd+bqb6+K`97icn5FK@Lf0ZJ{vOhJnaJFDzGdX-sy7 z2LBnZUz>dE^vMx@U~+GIx_5rJ8ep6YUD_>TF%w`<*s*`tir|(=2Vs5uWG>-i{f`9k zsB<_830Q57Sfm2Onk7MA#mkhlW5e_hc|*wFqWN|V%xL!+JbvMUvGAS71sjDL!VE|J z?{rfdR`;_^BWs5@4HWTuoIGXR^-F}P-HK`K&os9&4^Ksz;=KZ8J?Bsy^=9oe%RPze z??0sm7gR;A^5vT6zAIB;wa;&>!`(s)dP4C(IXVwfk`i;QQ`my*USNFcf?>z`^SaAL zuhCw*__as@w+c1g0v^x1?FmbYOm|*<3L_a6S`XV%_ShWO&(Eg}WF{ZfrfXJ5g-^d} zDY%@B9||)c(I+4l9E;#03gLeOf+M4wq`*cp<^&W1_?M*vp5v|d zPV<$K^b|Gp&e7ykluDB#y5hs26D3{taMJDmWi2_%J$9Uq%h7W_=5l{i>SQjSB`$t*mN#kzN9iSEsBOhfN7(iyU^ z=poTkQn{{OIAR6Sw1kPiZ{IM;NzRm-Us5({+7|50w;ia;H-RM%3`|6paFjXgd|A8W z|2>9{L&IT_#iIyZPcKeUDxY9_15`QH-@K(GO7vat^#x*>fXK+_moQxL&z)ZDLLQ(m z%IZ%#c9m0Yq-y6jVqFR%i+I?aUGcQFa1N44X?E^EZri>o9WW_r>Z@zgcFt)>y>iBJzCT zXWzfr&DM-UFh8;Dlx+EmjiFbP71|uJ2A=EN!m zq{3=HS8`mlTyFZi9Sv9bV(7}oQA`Cryo@IV$Pk~;oCTy#|6g6z*%DJ1#rbR|&+T;5 zUAr3Ixe9OqC=Ek=O@poOI{$}*@J=6;>t9E!^9`-c>w?gi&mbQO)SGmQ$Gp!-x=j=v%^KRyP`3s`K&s6xd-j|{2O|8j` zb7BKV)*|!LV$xtqZvTHMy)Ci;DTv`+nY-dy?hE$V`8Y?QH>}_Ny|Pg#)ZZnmKsir+ zq@)4H1p$h2MlHDAyC;4q?e!T5x))%_sMB|IGI0L){_)Kzrm>M}cV5g2C~0(m zXX6~dkTs066MT8e*QpO!DQz41=IooTjP-*NNgfEhS-BPJCor4?XFq?C)=Z5X?>{rVoM~C$oYmKVAmQS@(>j&l7Z@Sces}-?MdCK|)(_!9?#M1h}Kj0R*fKSz`bp1))hy`WX`CheS~$49H6{j3{78t z=LDM=_?DrPH1l)*_>ff1y5lEX&+fd@DPf^5<+~NjEZQFewU{Q5bLcnJJ7O@SJci1T zOnDqL)9+8rL0+920|ZL@LLh^ig2BB7cfVq3d7Q>Te>OS@-4y4Iz^(XkQ@9nEr8 zQE%rHyD0?mw>!K8(|4lK%%20i^crW*riLuo)K3f~TyE{vJV$uYDv>%o4OX0nC$XJNR$Nku4YU6 znkDNeRjo$U#+68N3@zj$qCXj93u~|Z`S{=+(-tU&#_d<<&Yy`r^M&~yShLBRLyNKN z&o@m$CnhgDJm{z2Z+$K7f;BKOlYdI?+ppXGIIWf49W)f_M|r6vfhT4`#GEkE6C*(B ztzSI;*+36KI`{0U&25)VRH>Q$hf{kD$ zzS5N?@~^`IJ2w_yQU7}VFmbQReVGl@XIE#;ic~4)$K7L+@9P+4a(GUpy`%pS^`HbE z6)m8>iTJv2`Q@68Xz?;1hhh?YU6hPtBAX%s^IH5`$l|U$QtWQt-&O z+c|yNd6`XK;}31|xz~`ePl=a0z4aOu1T!ytn)b0h`6SgRMqbx|BZ)Ja<5|;@8aDY$ zKMO2-D-0pRlq*h$j(DG&?~`W2)9na}zVCU>Gsq}54hIz+qPgwN$uE88WzT~< zX)7i#l@2wO&XeZ5st`kOync9>jXUd(`|;QtYxMT<4iA=lOQe{V)J^k3jY|E>2Sa6^ z7LYjgfdFmcNnZf+4h;UPG|kM-93cv6p7>~JeQYzfM(S5+xo?4^zTjw_V>-oNz22`C z$Lx<^iQ8o%_9DY!JmswQlNG(0IXpJ7-!n}p@1MaPdaQiRUu3I_>C6u7zR&Mm^HLbf zh&M38puEvxnzA^OMOYDp5H2F*DuTDqMa(DGb6k68ym@bgs>j=AC z#ZSB$kNEt+;czQk4auoV@AoKqG1Y{EnuBE(Mji=plR>Iz8y)@bHpAdNqArpHRaCPh zvJIH zOu{iIVaDCb^v-^iiU68?QfbJy-tDTAAM#PMP6J9Mk80DA8J4pCrmJFvos@y2Ll1D@ z=C8aK*-RZh^{}iCa>_7y$Gqz8j)(WS6GRzeTh4>!ryBgygiB1j1tIx z2yzZYOQzVCCOFUdMogia0`#zRPd)keD&}f}i1%*RzNqn(y;%<%zIO@hGlokbyWGxq z$?}m6d@pgXdHQ0Zo^Y|T;u5mRHDa``!*z$hTR>@dNk;5532w71!uTylj#65rWI8OB$nLS;{JpX%NANQ`U#0y#w?7(Epr(Gh>nxa+m2DVNvR&WgFJ z+9l_9)aH~J2QSThdfamfgkJX0#le*PV|8t#=+D*A&Uc)K77J^p`%QfB)<;t z1znXf<`3>rd?iHvu67ovB?hIR?#h1to10b?0zmuccyN;Zjj@rT2guVaM)x4*Hnr$D zH|Y5M)qk09gX8}b&i?;@Zu zogq@VSd>Q#Lj7yRC36did%mNc{Nz5V=A%?k6X5`-kkYDNQ7)%AQYr&!?zG%_vul&2 zDF)#xzd9usJ!LShQvjlyY%tpY<~hpve%2i$U$&4=q9(BHNNM3XNd#TT5$u96h)-?-Jzug$CyMXOTvn&qVEFY6i zkgV|)&;2rVhp@V%=Eh#%6g`eR-p~MQMw!q#dvYj<8fRZo4p2Qt0$CPZM)&VGJy8j& z;3A1N5qN91`ncDJpHAdBI+ApAmW=&hM5`l9VXg)eKRxSQPnNb_mEbE4V-SBS!HIatJstf0Cfwq^oS6)Fq{j1u{f`0CV%(jVW?iwO8 z&Gu^;3G_WzYI}r3;;{eYaW!#@-2a}=oxujHVE_`ggqih$JbwsGI=)#dC)U(Y-2(xZ{FN+S=B(& zwYe;6s+Q^DOhusf%ftB*nuL-F()PCbhuWqhW4Z4$s!W$K83R}PywES625H|LbU`-- zgVb!F8}YM*0nslwgY->I{%CHVmJ6Glr{?pckCk0tep)z@$T(+iyQ*1RZ+SC^q_mNB zto&J$w*H?u+pST^iY0L;t?fL9muYP)rXjGQ*j5kkLTHse!+&Ht&`GGNw`?jcMbpVj zwsEKHacOYVe};GX<3C0{GfdOXd+svK!Lm~QW}CE-+%W;jVD<~By8{%Q z*GTVmW9RTo_w^1)CSFefpU}fxas95QMGph4;sZr+u21{V))9zp`mKVuMuie@>1%VU z>Zi7v`*!wUgS5EFlg|Ho7~M*XG9xjp(p|x z{AcE}m}Y8{+h!np_0n;0lUeWPn&SNpKN7qY8uA}C$jLdg>EEFz_r=f=xpVw*FY}wu zsv60gey<8wHx_>uhj!4>DR41Cs4SqXn`$SMS&gz(@FQ+0L919)cD3BJvdl$r`FP#{`p*#_>^eq+~k=dKrTkmIVm~U zN7PFAV{WG!FzBS%1zw}jjWqPVmB_u~X zLw2oc!r?oIVybzLqL?7{GJF9^%eQll{`tkW58CIk95J@y`{P&v7OWug3PgMZwVUGp z$LScXwvn_nZKi(AA23X$bKm~1tyk6{N@GFmR?Q*7b1qBoEO9IR-)zCW%~zHg)BpTS zLwN=Lm(hD}g!Ml-aEK+SpyJ&B>5Ex#6l{V9l12W#Tt=Ne;IY0GaxrwWgrXEW{f(kD z;?91UWu4I=ve%ovn`b_oz3y6!pW!?_l$krm&k#?QJ@nPG-bvcgbqqKrmj+E-W-Y&Z z!Pn#Y>Vfyhrff2^^s4;N1Howy}8H$*~lwtR1z$Z;}?wyE5%oJ@ST~e=no^3)1Sa5 z%-~-VRVs&h{(rsnEyy>j8Mb_O^OygbCG7ccp~uU#dxfL(%HT|ge%$zo?k|sNciG#3 ziCZVOqSE_9zTFN88w@#a$2sO2kkqETb8GFF*hA2hH7hIBA1VI)1;_E-Wtu}(%lCms zH8{FmgLaVHWp*7T1Z~vhHk_FZ+hn>YdZHZWNV-P^oQ=A$K()zc>duOJY}(Mb7IK`kZ#0bXCAIQM|^k#bIWR^ zBIIut#YlQZkIj9*J2Uu(ye27LL$-3_s~ZS8!nZPT2hm!*j;3~7hu7@P) zOqSzTP;P=Zhq00B{8QjHk{1K+X>w#pT~usGaC-rEzIB~IfJ zoEz&resRj9a~Iyd@}G^f7zxE)mu)QmhqR4MN}u*|bg4L|d+2So-6TZzUy5IS_Tii2 z72q~q*MIn4C#1c6oZP=|SK3EU0&!KYLCa{(9SK@%`XPe}hRUbLGhYQGHBXFa+GO6+ z`FoUm!0tP3%Ra5!9e$hiygpie=N6%cm*`I_6)8@))Lse+K4#{Uxe zdOm+2BTbwyxi~uXu(4v`g%_)$ zw_p#LvB4h+kPM3QZ*nwI#H*@;9>|=CWqJ)#A;~RzBM+{i_K#87yrHSqad{C!JOOjF zo1ipuSB7_T=TXYpqKhy6iBt#g@126!;IRGo|C*e`7{(1`8~5X>xN0#^dK)Fgjm@om zL0P8h;=NvEeeU)GKq?bQTh=_wBGTKSHmhs~+#xrlC1bwd)7^Bst$Si& zhnkLB*Rosk-a!Nznj5bn`{}hR-C}yLU$E>oU2hSG{Sey*pW=7@4lNHmW$rMaiDAPu ziB)$6Bt*uYMvD?caVr5XN9f?kGMixRGEb=?^Ejrlt8G=Bmu%(Dt`HQyWnlb6CC-f& zU7S=2*{;r}hlu<+&<+@5n8CH|E>glYvv)>+D6}-1sK?X0xHQM1Na$a$jTYkk9-1E% zublvrDmMbRm%>1Df1%T_+U=dg)5P?$y%?nI#l~lTyPEXLfrEONd#CBt+9_((Sre_g z!u*fYbNTNmh|G2eY(H^OSiQ%wh!^;BlOMwVMOETl^0wP(pY=&RJd|Yde&hkkl6IHK zR7&d(VmjXX^dW?0p0FdE#@dJP0c`*IZX*fq6pVa4k?e7~HR~}=xw57}U36rkce;JUOrZtRe_Kk8`FIvcPwj>Ut|6LlMj71z=O%V(c;Y@ zpd|w7IT0H^3|w01B2?rB-2Oc$%)ag6fHbdo08Qkn0g(^6?D&p$J{+LMO3I8W7;NWa zGI%I^-4iemBA=)JpQlSSE>c`O(LQTDx%?r3AejLHyV!qbkMFcq;q@f{2?x2cdY$5X z5Z~t^YGG(;5eq$bj5e?vPB$AoUP{EHpqEVK+GK8YpNZJzATl zTy!ke8+3?RBB#!Pz>FNWrFuA*6zMG2Y3lO%Y%a+|#Wynb#jdmJHEBe@lS?QA0i&v1 z6&9;cGuU9pD#>fci6=y?tQ$f9GK-rB67cfqXLxgAcU3(t38XKiPq!0BEQ3>F4KK1) zg1Kgk9aXi;hU9Z2#}pFlP|!8N61jqXTxUh5>Ge(4n8(#=n{?k>E*b`5ykgNsMjppJZU0D)W9l&In={(lIJV21wKF_GE|x zs~2*RO&g>&QFop@I+hv2aiBG5QmG=^{QBknRO;7Xe?A`$^`}WfB`tkSmCxHb@o)CM z7e*9^Rk5?=^a^x3aH3QMj6+P;JbqP`j2c%M(_!_H1kk82<{{AGRGE{bBELeWJt0iFDYqa@YH)X;3603jrSltlW z=mF-L9f(btlk4@`p{)No08`PxV->;oCrh`ZCq{51;$Xp-55E2gdAsME(jnR#boSzH z!}uP1)_yRhU6VhmcSCxu%a)X*P;x}~qtV{ALSuzb*f!kzCjsLl%lX|hllt=)j*Y(( z9E!J1?oc;kq%Fc8{G9&1e_Lh?P$GJ!EagaxG!9uvkH!W_!3eU&bJm;B$G86GSwSZp zXm)Si9v3``bT*hOWgxa}+&Om$J-67hexjf`>Jpk|36e9;$cgk0zvK$;VEg(~VvB%&41zK(C{j<@5i$Z0?Z zL3X>iT&#uxL{^(S2gsakznq(-zFZ`l9@tj^{xOhn96ZISn0=SH-rcT{8GmwTvmDd+Ps7K9CiMU~k}1W=LC;E`Q|b!#6NJ z8CtQFi4MMNqEvNwQyn9s;4sjGI|d?#bDa_spg!u4I?#*{*pTkoXjKgRnI=IeZS@6G~*3ADEltQd%h`Vz;Vgfo=WbK0|Mnj z;x)E~VrC@gF#z;g9_^u_wZZg}nB4E4!;!L3F+Xb?t!=$29H5{v)h*)0jE)8$ogrtt zfFYuz-OR5Usc>sO{ARGBu+^V5j@v!b>SzXQgu_VZGN1RJ{na)ya1$#B7@ZoLxlQMM z=KPEFfm)lKz>DHApKzx3WdgE` zBap}D1E_e=NJWo$9ld{EUbemI$F38THOLH+JKmk~4Gf5bU*jvKPRH@Knh%kfD#?~c zIxhC)ZF9alQ>@bGqu3FO4Xiq=8A&5C16rOhcbIFO&>P`IV6R{ z2dHO3+ApdfkzMKQiQ=FWuvanqYXTt`^(-6(wU+*{@!6!2R}! zT}rh#_Z7D&BiI%=+y1tA1py@P1pmn!Hd=@A+i2=JySN9r7ykDFYNNC~5 z@|}6kR~qfc>*EsY=eC|W1@cQ!j0XkH=pOL^tT;V{v# zg=;tY1y}gSmaj=hQkHG{g1?fe!1BZyxh+EpqQ8dIcyX?KXU%>;5Yp884)N;VnoJH3 z%Sm0~9;&?ztbcPSxz|B5%g6qx4+V^|X4Mfr@Bf@pfT`7W2Tj<8Rw8i>-YMTLk+8 zd&J23_v?Gv0arOM)N;I{L<|qq&-o0aII5dQ#2c7va45TaJ*lh@m;sFa*g*;1YMJOJ zErj`cUGP^oc2?|(NF!DA_kGqXboU+G zxfxb9T4x>&2jKEY7(T${Vvr{bkqw&SmfbhSMs@-&TR(zp)u|{PrNgb(CoTQ>qSc|Qi6 zxx#t3Sut%i=${jjP<47k4PV5rG~dJX?^h@6rQbQGu#L2;QqR}=x#BqEDo1%<0-E5X!8gA&>>f3Ra5Syccn6j%Fs2;Oc z6YcwIO@RbhiatN5D59w4#^!%(sHY+H_t2epLyhAmKHilUr+xFuy-juhG@otRbz%U! zU-lD?E=pmo_F0n`uZb}&`)vj;AhyGuNR*=g<~ctjilsV!; zknbn&r~}TEg&e5__XX$y>2&h5_n9^mWU&qsvT)<`aepy^x-`w>BJY(0b6z6TdaO_V zs`bPjL2hb%yA{hy+jCtG(gBld?QU~2t!^H673%nWeD8Y`W0ix!+|w0IWsdXe$1x(@ z%=zt$)NhYE#rIbXNI|LqL^2No;=4hTN9sB9(X10yR>c&ZPy;Y&#ab>Zv2_-@z9rx_ z@sw$LQ6gkJ$D*sb3^`8LGA`?)JuQ1KnwI#K$47ZR1JPrxlKw8)v$IZO@2RZymMNo7 zGA=3WA@Y=#HY``vYroNr*Y+#Yl8z7mqge|ny+JTY{~*=*y65v5cD_1b@nLC%y*D*^ zZ5}>b6%i*)x1K)`)HjK7CyG87GfP2n)Hcz4`Ct;hT*xGtU>!G4P|XX@fNLJ-e#`5b{|}k@LTWa>Yf?48 zzfSz8*(Pwq!lYi#arY#ebXyBSgH?=l@<-#FM_g-<6nhgF`yb8tRC~u=CqF+grXd0u zt@@wMfKu1XbT?}!J@a_MeD0$SL}BeCHGY$x{*W$;9*0{htIC-Nrd=6Kkq&AWqS|eLWr1GHV-73Xk_j&b?s8 zu%i#Yj<~GfyK^fgw_)jc&qu25n|gy<&s&o@^lj}=U8#1h763a zB0bif83&dqf?r1>QVZ34Y%V{HRJX5JM3#ff&Q()~m>e(!=H$;bZNkL%Ld&f48x0;* zocRHWSVzriK*WYz;;^K=j=Gh7FCfAIH#ie*;a9xP#nq8&Oe2J6|J3pCN2N%zelptf;gnd;vRm{$>k}}abJx?0UmNU_v|FzLR=s!-RJ(vUdQBk zCt1Tp^1z29Isk>m@y;oH3%EUgW1tc0qB`79~K7I=(|n< zr&>em&yHyD8S=K1#s524-BhRa;o0`2!M>(_Je#-wNSWW+a(JUD`^5(9)0-=vW^UUh zmod&6zF`|9skWDH@PU0}6Nd7@U(j0_hO>@#j(Rqs)js1>t28-6KHt4t)pOuA0`Y%jErPQoMCDwcIwFt zEBio4b(#`#S zga0hqudrZ&#x+K==Guar!YbjL*q@&l%Qb+IZ}3gH-JjnuOUf>Y$?Vx$-9d02p$;eI z_|z`2!=q2XJ;tls_M+G}Zda4)n7v@i0cA1SJ1*JYj#x@0-;y0D!Dy>_viomAo$w;! zoz1E)uGl$hliOC0;nZKpF}VfI?Q$1(`6xsLZeVF*KDDu&uYQ#raoEV-FGthEM#+r1YmKCo&+|Oy!3C z@2fqi0seMFlfUCFFoOJDK03z)T0K^dg2 zsp~@lQ|Y5G^E%F?IW!r?JK=OdjSGrsN)h|RJ?Uq;zeGnwzP)jQv;)jVs1c*lKn(p7 zb~>@C|D)imbXTU6St;rwr+I54@!4*SQ%Fu+_ zgIQufRgtJ(HSsZTwo&*PJt}$ z5zq5J<^MQ`Sp_3Xhk1?fuY*|>iVw<$AwCc3-ApvBk}N?UQud#J0o~2AO9w!(wsvBq zw$^G4Gh=_#`rF&;pdd?2>`DXS4F#asOh>BAQ^dr0rN%bA;lpo)m{+Tn*KH3(RKEHt z1BBnw7f}~h8=Q}!RFYK3;4Rb(iYAKDGMv=u@f>6lj+}YWiK!8}rfY=hgj%gJa#O}Z zoB34vZco(`^V`tlLACXbHOB^w6#w@5#@*UmG2hew7ryhuO1rSKTW6(?SHFs5S`Ew{ z`+8z%);VTl6WUwI_bJe{}b87>xo+Log8ZNt?Bce2=0gk&HF72^z{Q17Dv05f=W)(J@-zPCj|X=~7k z%_Df-QCN_$*QascKFgCe^h(2I3~24!ma9$qTeCiaHoe`Gr@g4G537osa+0)m-@dVU zW?buW7=g2}{ygS+1tJv#tRYbXVq?2qUJW$|^DS43!g|~IaPnPwzxl5jb^qQz=+cH^ zB3B-&-F6N*Um9C&MjkQ=0NyeNgyVDSd#{E6u3Gfwxq-00mS68DWN9oEz#o}*zX|CD z?U`o;@aFzD&Cd4tTGTVi$c8)doGMuSM-%d=@3+=MA->dI`KteBW+f`C8$R5K4bK|vgul$nO>EQk&0wPq;APHqxnhGGYuC+*!U*wL z*5)pdNI#Aay~Ec@3-P!b!=vman|zo0I!8RDYD=_xPJ!SM^3*Z4^gXE)dwiRmgLu{R1h?3|UtS-D1MLrGZ1aq4~uLMPFKot{n>3g=8DGn{VD z($CxPL!&Y^505R^^4pg%-yUt+6*)?dJbH+_%T_WdF}DGHk}H+1>STYV zsyrRgVCU*ECLj26%4Ak}Y~;;ZVnC{fU8VDk5TY&t`@S~4^q;*Lw)EJ&dY%##gSS_( za9Em&oJ%EhQ!mc1@lfv-L$`RR~)ImXv;6KWr>0 zPI<4GuQ1-ym~W>gh-Q?cs}vzWSDd?BoFn`0%*qdyQkOI!0Atnt=pJ)a70{y%LzQs< zLyFTYKC=tt5C6+t)xHC{l5HT+`n!)s)`Ue)Z`cxKJkW}Z z`{p(Agq3_+dW|9>R{jGU*EUnzU=mpMxzC8m@|`<`OwxJ%@c16v=fbu(i3Om)KpTY!;3I$PqxF)I z%58!(buB5YUq{1o6FYuC0paGdgF%iLdOYDq4#Lzim=fz`!f}-~rvSy(g}lW0oE24U zd4Mw$aM;Avu3zM;R~WMzz0a&|7FH1CWxGkv=pKW~hHOD^!VhbMDVC>reaaGA?oKt~ z)vLW}xx@+0G;)o1r3yu!3U2{8%d<+MKB7IlRRV z%l`jO?}ql!8Zay8ky|_gV(^$jDxr$L3_z+8?2#)yqqkBhm6OdaiyktV`Y0x|fE11iN!{>1d`bDujB!bn$_w*0a8Rd-ILPN3PnXGxD( zv3Tg3JS$c~*YK37jbF*!I$HRK93T-tjH^bGjFWfJmhICBAm#=hmp$bp0#TEJ%P_79 z{EGhV?`+A>aw44i@=hexLEk4YbT?qvkwDGGjdn-@!&O*|0s$DLy6)+0H#L0mlbuV2M~J2@X0ZM1JP@|FE~kZ!?o7r#OFMwY2d~Vr zHJc1>tv`lZ%DSCBf=Y61O`K5fg|h5$Nc?J0_!vt1fMHkvwAtBdOwomr{k%f! z`$8*RnK652#gSS=ttHHxKF*h)**QzU%5h)VzY=-LyuK56s2cJ*m$igKIQ`S0TB$wM zhS7t6kzBxVE#LO2;^n*l)H6>rKi@~q>B+VC;aNYrY5j`y;Cwk8CiK#kHLXxPV(I;x zQyKRtsZ-a)%8^@CV)NR-^r~Qn0)(R3saxIk10^(PQDObc$YnEM%t|^Dd{CX3kS7+O z@xQSDTeikJ;kf_fPLXJyn|*#+eoNqkR&k+Cf(jx8Sk!oRH=iQ|Umh)gI{Q=eU=G&e zmmzfZWlp3!Rpi(_qCRPuQn$|?#Nn0H-BYm-lP!|?7H!T9486(P)6A(kXp<2UPm{42 z;>ngd(S;?2AfQhF&$7wlA$r4!>rArtZ;xFiPMTiF_6VrwROn8Sr;**WmEexRKVMsY zh7UNZwZMQMJ!=S;dBOD<{M*)|!^`W68&yDpN(FnfKG5#8Z%z8 zTeify^mRfD`m{&9Jo^lQx*%!uZcAYQaUUSYo1iI|!)3Sj(l{;)?xVxpzoJw0`daB+ zqE%iOfhmbW1w#vd_g3I+ccc@Irm1Ncu0L{)oYd?DPn?08>zR^qeRK*M*s1>y_TDS1 zsXcrf#EOW3ii&hAC{?6Mw}MiY-Vtd+=p~duB7&gOM5H$r0qH%I0HGX;RH+GsBp{uT z1PCNRfXv2o{xfUVT+CYE`Yz^T_Jy!8+2#F}{g&r_9&Z^v-C13GS%+m_9N<_Z`Eqwk zTviA_RH_^?wX0sex$(vFms)pA|&0xY6g_``cDt*-=8WLE`QS zFvfq=Rie4Er{38&wwce(k zv;O+8k&e|5fS!%F_|Wb7jeqz7JDSUm0nkS8ey|^Y2u-#DptPgY=6|TmKViLIgn?;* za%1k3mjx%ci{d3i}_Vq_k0xOMUY z2E3o-%?vgO5d#5n>t!>V%R8;~%R{@Mj~k+(m|P+C%vJNjYicM9hiu|uVzW#=*-l*e zFm(xT*ik@8{!o8t`pD6OAUVO!37<{Ux-Q&396SL{SW#LPtJ-XL&1^{;xw$jL7gSC3 zWVocG_GpL9!`3?4K3-i!f2e8Fgvp-emtbRh^k$5}&r(Oku;S9SUagul73pzWb)Q&u z&0%=ed=J-ms+eX6<%6uI41v%$(yS3LSE5 zjsLxkgx-`?3nT4|i8+}75;zv^#XDN9C{$i_^lN?a(4pD0LuNXNm{L8|YPuK!av7M% zhQLZgwXadWboJ|cSE}k=Ms*eT2!%;HJ;h3(Y;BFi95Zz<;mW{1o1~$vrlD`x7bEkT|g~1 z5?{*K8xe-ZbMDY)^F~^(kbLwpx#|e{FWxB)H*(y1Pc4j~8y2y++hEwwYW9ZT8;1=1 z$9LTW@i*&VkLH+bnH~Xwo%vL-)b4)y#s$XV%U^m~^>%tV&qVzq(T#>MAl{|ti8_n| zc-Nln7e#_iY<=@maa=h36W8e8QXOD2=8q`H`B?8mSyfH3Pz zVw!Q0p#Pb2jq6BGb5_Y$%{g9pwfr-4bR|A1o_fWT&&)LYefL!Px!@&9$JLAYtaQ5G z@{HqCVr6*(2joBHY$0qdJ!3LzVKN)kZzqcT6);0QqAhA|KtuMqOcN&wS0uZ>!7T4j zP2n1!Ah%0BXd9l5cbBgfs3F2^Fh-r_{L4)K5xIfj(^ZhGL@oY9 zaKe_k4vT{fe%$(p$9DRa^O@pjFuotX&Bo3kKsSCwvHZQ%|F75tgq8o_?@0O^`~Ls; z`L7xNAF5hhzlkuKp69-el~lG6kXBIqOJ36OvYFvTUqeCH2y0}414e%`5PbjC{g;j5 zY{5{{SMfNt+aW!{fWqwimGHj=6i0V>8#6X#E z^BZ>-d~Uk60W_LGo0?xr|8z;Dsuf^c%D;y4&3K8{omr43=v@p?@JSH_JsQLm)iJ8y z@8>f=KX*^e71?8}`PQ>`lL39Z|LO=$t?q4sMIfE+oGn5sw3KvQ-Q9I|{lPhU99&9m zsvyZ>r=D)SieJ%qWG8$mgnc3E)@sSC6>m-+a}6&FPL8Bjl>1Bxu=d2i-m{|a4cEoR zA9(60B>> zeY8@)B@Db=J^nSJ27f!4JNMNQgnY!1`F@+zPS=XAy*8~_no*Cj?)iAzt z7T~1y+begY2D%fwzIYKNMNjFyG=U6UJcVh!!ha!HZ&SH1>gat{%!i0^TQN02&3UH~ zpq6lUA9#QTkcq)c7+XYiS8b=%J^0%$4fZmJFIilLr;)kLK1Fn8dd9y| zQy==kU*+BaDv0!ENOmWTa$RrTk1;pPwQ!XnO0bHVjdY`p+dR3TH4~DV6ShWR!Q2yj zsk1ddE_wcp?SZYE+E-wbJN2isV~fR_D7sG26dwDYWoN|z;39zbs!@f?@3==m2A&7hOOuY2gz$ug1dUX}Ew{>peMFE{Z8aDyBkoHYLc3 zbB7C8|9E{yaRD#T^}f&FolhkOSi!yrPua*%SSQ)dJj@uHxE3I6JM-z1T->MmJ{^rl zU}FGmt!Ill-9mL!(h#~M`-&|o?cn~A4rZT~z3-scM-38ko`Uo5PQ@yz zpSt?$*u4iVv@%*wlhY}?k&(;G@rZBQF9}by(MgkD+%|a%@8T@!93bg7fx9BTJ1#>f;jcNdy5aKL4iup!4Wi|l7 zQf2b)BvgUmM2!#oH2@7`ATLaTE5O4W$cfA8dfSxXJAk*+I5>+ifs7G#Dd2al2MhPifpxINS19C~ zc1p zB<2kV4(6d-$K{#Re#_R!yjo`BP4E`g-wDxsIhV;t?Y(LXl+Wq4RhPL}Ye3)TJ`xc7nlglpg84uCM$Mf^cxy8M^jaY9{ObQt|)XkyIOX!qC{Hm@b7} zL=KCGAb@Vq*Uql(eaG;uz^q;D3_OEzS94Ku#n{$v26KQ=5r!k{tsTPK8Ry_y^~Edg zSox;+H4p_?aZPE;cKQBxCR9d-!}b6tu)(o0K0Cv?3ftv0<#m4aD9GppM0OwONv(7Q z8k@hlv@HZ0_wU-&l{YEf-Y+y>U08|$dI}C3cE9_q`b824_ek{hcEJEORp=K-d)aWJ z+U~x}s%oV~aWV&7%I}wpwe=p>=!~5F)er#WZ_7P+(DCzPsRPgaHE`8kcWp~_5=`rj z`=cPKIQ{zQKO-uxA$KAl7KAtQ|Kp)5_HFN>`SP#L!@=1r_-}CDv0?z&?23kDh#e;) zj@{6PxUZq$DyDPgw$3=S@$0X@M}x9e34oX88n?!^)2J-tSKSXuouww%K;Lj0(QVQRb$HK*uDd^5Uw)Ct2E# z9FS&LOfFmqLGR%cFxVj@y}Y~6i#J;IjJuC zPnEDWr$>`e(~azeMb=wA(?3c0ySG5+=z6P*HWyz6Y#ygCAhCfHI^BYEC4oF6u)W6j z-u2=8!kv2`-VcPjv^m~)Kkd=9b*Xt@Npg0>-@3CFMzGkX*2kri6*+;G#`<^Hmnh|A z#n^m2{TsMF!Gr62ZmDFcFyL+8q;U9{BCdKf?E`oQ6gZR9CEY0r*hUU|r&h4DOKmn} z4%?-)y(Fv_skYb8AG}Rd&6fc8Adl7j$=+%ZG+ z0dpOVgb1Kv^`^sM49xmCe(&q)e_#Plr#wOkwZPLsm2g3z3xa#qTk#x>+1lzweA{ov zK~tgep2`MU3HG{anFGrH$fM~U%@Ur44BoeEnbDA=-P;gv!$w#TUR|awQ@OT znUUBa@;r^N$+0PI%juB&t>M1zHP=}!#t9l@%tn7?zZt?flKsLiJK%wZEWetjAi$9o zWOsOqMk-+Omc@`27eaO=lB_P?5pSckcc zXaDP-Da4nHv)8mV?euP=ag3N3O0Qwj57Ggpdtil}eBIxzb}$P&;gJh%JKY3ELkXCY z=BbTsC6GD#U=fGJ?{*o>7$1SGEnX@63BwH1(+brNSS*|OIJfKTY13s>)eH7b2Lk@8 z$w(go!5Zs=XR?IBL#hMc&lA{!SMLh{+()`JWl%Wl#8@#E4y#0%w~RO(WX zmwv~;%yp0&H#<8(ku7xG=RSm`NPOaC!#qs;!q~HETT?@PjLY0OHAUCDeIuE@FJCh0 zf23hyj&pwr()Lj#d(OMYQA25bTRx8sn}9{|M(Tdr={~$_RNOOKj@|)ZGfhR8vH^Po zf!R0Zr)!mPuV3KE!&bsHb_CUffgODHk8{Sn9s!QH&wk_aL>; z0Xzsly@GW06K&}SmZzobUGyYrhj^LV$=b-k_;wN}<=3Hfu+tM+TZ(eg|M}M3iX*3#E5V`@vj_C0u(egRXA;W5^BHvsfp2Ce9?=rY{x$ z{CAU7`|CcR@E&iMd*0TW2uN1;+;WTkE}HId^THMqbj|=^NBGN#a9qy%^&uSGSA*Al z&dZq(G`PA5u#_cQYYe3hlt6v0u&gqoUzX!sFI6ZhM5j}o-buOw`m%CK_q9O6=H><| z*o5ArPh9PThKAAMR4t&lCapbEPGji1I3m0q;6$U-W(h3OuI5^RWQ9mdp7AF@JzC!y zqO{0?i98|3apThjJA4t<{`!!#Pf>B`ro;Fl=zjsR#gy?V55f-GNF^PgOi%wUn^`3Z zWjZXW0b~eG2sXBorj*Is-~RI5r^1UNN2>(mg|dOJ$*0@^%&DFvBZXx9dQJuyiM zse983@Hlh_MHjyW1D^ZR4`9U(R=JEbj<>-XR{~#TZjSjWezaRn*C@GtZ)LI26HKeH zbB)YVY$e|J9naV=7uWfWiYMt_P0i>eiISa*QfbG*#4|!y8$vwCP7iIQ0yyyr+AiSI zJ+`SGxzQM2q77(gX;G{9NBru#tO5tW`fCrhgJ;wwKa(#MPn!bGi*}bmB5Q>|CM z!Ckq^jwidMSTRhyvZLZ5Mm`JoU!5bf`oFilpg2IyaT5Cehnb0zfsP(>dTsDyl->}<)8i$V zsh>8r4KA-1c{&OpNWbn{M2mg(Xdw4LWu%()e+1pHk2HOShRr5h#6}+M6wF$AAC+#; zyllq7G1z(nLk>)YRGSgS9UQ~T3KvU?!Hz+G}yv*t@Pd^BnS32$O?9$ z*?Z2Z+6)rc(lQS!-VCHu&cb_@yhC9pN1RI}y)ARGGPGVAcal;?SKhm_}&M^w+kZCveKT3jOB6Af~KvI<;@ zvsq~SU=V;N?s!1wZsS5O1}2g$6Sk7J%I3OlEnFsm=Ivv%vxM8Ul~SJ$AFwk3T{Bk8 zXyx4vMI35WRM)}_G*IXUo(H4LCUXa`n*nSnHS_BOJy8BdLB5foNt6)0+TDI+s8#E&OTB&!FM<0tuK~ zQ;BXP5f99of2$g_HapPz1xruQOL;?h4_lH7R4pEvj_<+)s|5|mIEuK4{No%R^xv9K zW0321f+J3SsafXDj`{T#d%qrf?gL5@Nl@5rZE;l?^C-J-j30~f539X6iFKL)xC3h{}0+0)BFk4M(Sk{T6U{O~MJWEzRGL8OO zFJOm?{Y=}j!Pp3D#EEDv+bG1!DoiK>q<%%ng~yrNF>c@afadX~>hQwlR6wBl!lV*F zLX&adQF`x!j5m+F&0{)ZOwp~jvb;HJT&m>RR;r<%V7@C*DL*^5&==`;(VMu?4zyp` z#XXjoL-@_55f{fjwpM>^CbDwoGx;s}O{emX9qPbEL2 zsAMAc7Uq6G+(K!Fc=Jn!Cv87;IFnR$@r?Dx zZro0aFgoV$bkx4O^S}bt<}U2VT$lfpsK%I0PlKZS*i+#<^cD+RRuOonC{V`s_k^6L zVRpgvv(STf%L?U9RUZszsNjPrYFJvj`e26t-51`9fjcQ`)E6P0(esbE9kw_qlp(?* zUQer#`mJ@s7_evFR(681fNpIBdeFHLOAZ!(1T4XXMwec*q-Sa`Mi#A{l{!zhwKV^r zBzx4~3LykZl}Rx1lr`O|>t~|@4NJXggYX^Q^L8L_*B2wFp-2EOduAq9&hztiZyt5z zGf4hjcs+ensu#X%cjQIMKoA-l+=Qa-4-IlXjEmCE21dAKSG5;n6i@|KGNO2maiN_{ z7P+=bli3MTMZo{p1e3^de$UI(oO*%eNEJtuUJ;qTeXn!Mu2$RQ!u9KuZ$K5j{NBo= zal+nHF6=g3+(87R)3Hjd9IiC0OYEz63<b@MhhOuFiPAQztJ(fwv5fj=zy!dw=P>p!l}>ML+f_ zinG>cCe6gzz7&Iip|t>&XR?;DP+Y{Zemq zX<^3L2lGobY(mpg^ScFbG+THD{qvWyk-jn@|H@fMY1z4Uycd@%f8t9>o5HiCN!UbL zCfUQhp+t8T-faoeLE*M@Ya2t+oaP4R{mk%#|j-llP-Zm z;xKbS%e`0i(id>v(9J=AC!*a~KGD6dJASP#_pG0Y`!B5D-OxM-RiIzdC33k#(s>G|hfPd!00@-6iU5 z5mZd6Q_3$_dN&-W+$#6>vuZ;D2CP(pBSWA9un(Vmbb1K6ILgO4Br!pAOV5f8X z7x*4`C!g}V5^&`h^V_#v8OQkooSEN-yTE&7#9AuC6v~txK$ay*v2V-eeD0OPEFxN$On}MY#=0*5dZ%M44xL;3l%sQ76xrxooc7 zf8xPAg8M^hXbO2pS8XoWycj%S?ZsgoeQJ9}5}nr{?^XA}gC^t9>6a#jk`68EsX#5s zIu@Fs4~A#YsVsyp=7j#!h**e+D8->=KjLibeWJB#)spyT>1NSy58ZItG=V;{Mu7I$ zG8)(xwbMi}LCf(A^nmX@nEmy`kwN9?J9ga)Fv1w#4zurZWNrS`p#d)2aKoG4(1#i7 zJeLXf$Wy}6xm(S*B0G5?cJTh_bg*8YCNYGYtsg9Ko(%(C8x)y^J=hZR0O37`8i(^= zCKq|4+$r;ZUd{!S4n*MBKW*6O$y2|Z_=(%SuJm5-)hM4i1*xNOMnn}Zc6qOPHNclOH1zkJj8ZL2MLTD+vKaHDrvZI%wOF}2 zo$V$T34LUH`~65;6?4M ziWw}r$E{l0q^iLyfgyJcEoX=RYc-fEf2ISK5dk9zkhdO5_do;kCME(ex=Fs-ran-i zIZX2MGV=>oVSNNy06PS&OJPXlhiY+dWyll#VK*=KWRl8S7SF-C8ZSvg*ZRoZu*sIQ7w^C@~-k~Xe^b+1lhTjpdL!-SU;b<)nA zmd%4~e&NR3JDw68-`>}Robhkh4zlkQ>W9!4WE0n>14PTx!9RnzFAL8Nh*`S9>SH6b zmVEMx$_tt`{!qEXiA$#W(_YomFXFTb6(~!}j{P1ts%t|;j8x!mtvDmw5SRKfPMjd; zzC!8Bu{d=mJP(BdC(S>Qrf)pAj%uA4!;}ibu@l|ckW`6{Dux`9#bYGvMX*fSdWQ;8 z?UcJ}TRziEZ-#LG7 zZS#e7-H}%;8RLSOuddU1E-``?kM{OK(xmN9^slFlxcljK{3cpVRe)zcdMAg_CX=1X z!&xC^^+N(x@w7>eCI8N119;UYGx^LXX=J+tx#yMOU%OL%wjw_=q3)wkGEH}F7na9Z ztZwCXhF$ci@m;qs?d>CN1DOA&eT!dv%2U?T>rw7Z&6jL>ncfJ7mG4JY%zh9|fjB_4 zX=DFD9RJk5@^Gm75)2#0^db0P>Z>s`*+iDJF}1`!Kp%{uNd=tl$;Oy5zlR+fp`@bi ze#@2R#^qAwf*5nx@i!PkVc}Lq@ktG`i<&1RhzTG2-#3B#l7IO3?yk5VV_M_Adiby1 z-$@d)Cm45E&XqytIH+B^#>Dhn1E>cwL9fFYgN*S~cLr>L!E1GfiD@_d@LV1Xj6Jde z@bN(u<9fp>CZgOQ$OpJZYRIlK~Zd>uSo#=x=34SWVT-l$#&t_vK$ zoer-79J|rLNrB^j_Bmj}0>_eco7~|~rV#c2%_l+rDAYXWd@;*XooniSlyHJ3n;79n z!{2K`U*ONeC2N#Yja_nitUTRHOdvs)ZtB_1nK(h`*`2^mGg*#>#D=OLvwA}}<(DyS z)Y=dUKey-~Mrh~i>_b~JF>Pa~0Iav!&hGu~oQal{HEUQ$`Mz5=>%UL#F5zl3R;{`z z{*9#Jva-A?--r?<@wQR@w=Ms*5mbJk4MV0GUQQV&K{U36wRi+IMP)x3ySxSl+DO3! z7qqA(GPRym0~4yDH&+!oIv8}QMPMELE7Qysp6862xm(Hl?Y(TK0PUK?T2-HUmHUyI zD2O?qPx4M8YMfpOHpxo_k?l-pqacM!IFO8}NDLU`PrJhH!nkjqn(CkuLL`s+U}wjA zBR?8DRT5F$dv?~miB7+4F$IL>p6a`}3VDLN(J{B(zQv6RJBN-i=pU)w=R@jV55o=! zXXcG=xv$JU^1OLy&~1f~$ns2McbT%OHh3)FvM?~PbXJ4XbNrZT?~AIyA5SP#?G0)D zd1*Qt;*yqf*@M878m+&0;*_i-TZl2g6YB4%7XxN;Tb^rXN#!(Gxrcf}(RY%B8}U68 zl{FimiTXI;>gm&t|FZx;okN)nvK@E(ITP71nV0u5J;;2E_G0`C3oJ^ba^j%yX1*E9 z_-e`Ma6D=}k56)2_{6U$WS-j_v0{~xWlWv~&ak=$z-kw4-u9E9UZDLgl1`G-t?Ho$MV;RY-9$D4eKgR1*6mF_nh%sroj;Saq&3 zZFaz}A5P*$Uepv9$fj@HGZP`<5I8UOhCLK-JL#x7LL+~?Mz@lYhS`*!outjVut0vU& z){O^6+@&qc%3toPw8qBX6c9r-b&;s7#5H1pmnm$>-xC_c=0MjCxd>+2P-uIxQCGl*JBH>9F8#8pW3^fWJGIZ!w z+?hT}GOo%K=M+JH)h9Hn{8sm>REe#pQ2YQUg?l%Gg1^Td3nF!`Y&C!H-CKdyX1`2S zXmIP=iZu$R|DX*A(Ti1}swPvT2kDMqMHQKtSXNKq26mi0ea(4W>ouC6!P>xNjFY0^#t=^eIzbJoav1PIVpm8lRwBV$4>3wrE`0M^M2gZHC~Hx+t;5<=1>*ZiA400 zp>02Jr&fIQz!RFPajDNxjjUo-tx`KoOpno?D=>}M zO92kohLs2wo5HTN<`74HG!;LXJHS3Z^+9uy<63*~+eX%k9k;22*gW%FwJz5nK@IHg$ZC0PEvQL5Oh;Z>* zzy7G+ZeDgmHEw$G58KV^1o}a|k>hB!zd3KsKu0dAxAB9&MrBXT8IY%oL4Le#IG5zO zj6+gP8ZCZo)cgq-m1{*`kE;((Xcc}iYHX@9{ ze8%UqtZw*1+~R%}b%Ie$jeD{gcVAn1Z^!jb^uam>kuUs? z7+%f;v9XbQFu4_LV%emeac9{qj%E1d!j=s5^0m)u$ppco?e*pX$hxF}Z|B@GrnBeH zpVcfJ8TPMjDURaC1H9(~)@9I-eA6mEsA+>kQS+ae0;LNlGN&PunD79|rTn zTGSO*SST~+0U{~t8|{aU?k?e){vkiRRCdG?NH-UbN#HFk7nBisUBvqf^@YwMjm7y& z)@Zr7$ZMffjn;S0bhN>9Mwmz7!>Qaopqao$#QoWNo7=Kn;tSPuctQJT2l4d z*|zhS*gr$MnkI}(RnC<_R^N8fS8Z|WjILlgf4}W-h5BB?3 z-LUE7LDTcDMt)1Bh>))qzT0z`IAG1=@ykau#| zAR1oHq+eU7&4YO>Ye@|YCCF0$#`6I-*WT7r6nAK8K%W0w5oLU=9AR)CM*eQ4Sj)N zGvOhi3lZ{#0LLC2^gr2|zEPYf!n-?gjs>$|nJtAa(fQrzvb6pKW?kyy7i{3C_6F)2 zWMojw!zZEZyNu=fz5Dz52)z`%jkf1 zW@Y3o17*%w!25)LEJwXlo>7W3lavbQrK$*%}cE$v)xPR}OJmFLz5G`QdS zdlfY}f!9M*Fr|P$HEOLz73*uLnHcBwhEKT>LQ`ry$&j><@Ua4rKfv5kMJoU3IHg%j zbHI3X4h4|=Ew?hw#z&}iR|b;>%5E%NhR2PR=NYq)zOKKxh=#aZt!%djFYc#-FD}&V z0&z#wm35zbQpHC>G8(dDh??zw3`%YL47R}Pb zd087~uJB>xF2n6GySwM$Wd;*+m=w()_;(Y&aaq+2_6Rqn2u#_EwUJQ+XQQl(jB9$K z8^F}sX7b2lcBphl9ry$Mo!T+ZHLOoaav`XkZ9)3X)^`dXv{zA39ud^;#}ZFH`Uqk7 zUBPieH=q{Vy>G|=^GrG`o3u5@`={vf#GDZ|VcC0WMk~l9-)$U2Tn57-D(%u~DQxMv zy{27t@b2w2@=>3cZo_-Kdx~bi{JGsxcB#wb9&Je2YX3TESakGYKm&;qE+H`3gB4M; zsnc$O*O4%$=9{kg;wa>z>y{tB=uT~_y949yOsu;YkaW;L-(Dbm+f_pp17{_g7{iGr zPr?$3Kgis80l0-^vh2N2W1WPSgsYh?&P88^Jk!>ZxH~nTXqIq!gPmAo?MJp4(eIC0 zFCTc5--fu~P`qur`S!`f-)Bymk^h9W>NZ~tj4`bv2*9zdJ44h?nEb1;J#hT1L$7=i zpRrlUXq9V7D4Zwp|6+OP#_1wlv$U1>T2?ev1U{kap(c-M_X@Uf`o_v>El)HF9TYF@ zN?GhoaGp0V{3f#Dl$`pk*KuRrI+2CzW;DSNZr8_%x_@8T^_Z=iGg|j&A#+Mm<}cv~ zfKNE0c`DzH#g?ws>6*PCA}`~J$z&Q$58oO_)VzlDfjuq!>(B)uSS{kf4_Q;i$}*>j zn8=&&hy$xD`3&o-st-<|-x^q4c@vc2N@U1#H9S3gMo9?We-KiTkmwpbTx05>q+ELM zMQ`-jKw-c%^XS^5Z9{2SyRmThq^)y;lFRmoyXF(kj%YdjR)g;7#j~ZZ8VZv(PqU`` zGC^I2tsF;fF`MkS5LF%!MZ1)C464`6fn@Tibz)CKlKsS z#AxVUU7g<1y@=f3tBsk6m9ka3Gk0~D&b&v04wn-T&S|k}zuv-MRFasC9&;ZR3EF+B zTR)iflL?sii(2jQ584aVr*_u!Rg1237gd_LPPLh^5$Ww+tBL_90$bk9w^09Q&h^TDqT9-nhbv;rXU$DXS!>MIcUDg7clmkd7A- zr7)dFTH@)K_+|GWj4vpm9aW#Rfs5+h7LImhvXnH}ojKmGd$xv4O7o)sL}Jct;;IQi z&!}O3DtbcBJo}IA%vuWZYZAW?(YP$;HJXa+eQlfyPG6b4WAzU{sLXCsuwm^i8plf! zC=|g6oZ{q()450R+u_jtPLQHpzWBM#x6HvrN2&PArD_%YUEZAz3}xW?+oWapY!0h? zFZ<-qQb!`(D9i)kM;jiCwy=mq(LT`ZwDLhDGZ4h&bFqJg>rZ95DP48Nd~{AmggkD8 z<2#h(Wn9S>%J=S;bio5GQAw$hjkff%%J70|4tEX5x1Vtuq?Mf#iXcGhd zU;JM2IE$3}INF#w^c63Rsa!+~xzAqA~>sz%SA_ZJ)qDS~) zJIfTrf)0G!W#vH$#8fXOajLH%!7yHJ-{+n(qR|0YR)31KnWMG|?^otPy{5Z(fF=!M zTlk%?(Iy0*iq@7d;_}39Q3JbiM_O=d*fYm2r;WSZL_11fxL)AGzSj)J9cCWh4Bk0H z=E1hZ%p9j0@W8lDN#R*8Zb&+GX4FDXGu`Cg8 zE!Jk#cgT7M@_J?U$rC5R?}NfsZoBzI&eBXwHo1kv_sw&YhZbRPDKnct}86oTEp_BV3{3N+=xqzkmFqiQZh>Ws z3pKAh>!>(C_QyKeP#q#APcXd!d5MUy<;otcDX&e%UphG~qAH)9h+N&H$TnnGnR}<{ zW=rrP$k!9s3T?6?`4LJX_7RW(^oX|TrhM%M#xIC{d zvs$0ROvHI(W#W>)P$V~*WwIo1%gYo`b(f#aANO6Qy`euJTG2L6jc+^|xnUkmf}skW z?fS%TRKwJVLkBU7OLa2Eqnfgt#TgB7$7AGQudP-B+|0R={4g;>IhJ$q#s06)of?(a zyz+i4u>N|N2284hBc|h+?CQHn0{k44douYlJbh9!FLBpSN6%(-bo=uAH)NU&kgakQ zE9>KDXx2lHYO>8I^74~1<}74OV%b5B_sR;sRo|U&z`kSY2)n+(;cl$J>CTBljE*SK zT)Y+@=$#=O0}qR9DsQ5rsxhR0NE<^m`EMn) zLeKr34gN@N#5zL+aUYNvRqMn=metu_`=HPgS{&xzp}W)+w9#-G}Qm=A9My>jvUbrHyAmH8t8yk5nm1=-b@?T@czUx zV_s8h{iZ!o`XN3KXX8FYP7Bol1C$O7(9Muy!t!L}Y3n=M{iF%bLX`(QH$8m5SC|Ne zC9XvXa1EQ^+c?m+2{g%ORE?@uq?Qx2o*z3u&YIcXhh$Z%gu#g{5OMGmv~^5~uZe-3 zS#5s~NKwk>yecnzL=*cUoOt7O|J^2S(aP#bLGBnjJY23$365HB>x6Ow1Kv)h=&SYxp>NT}qCV0B|u zdtOvfuk~5>i0#Q*=M1U2%@NlFih7svp3JL`iJ(?mSTfZ*{s{~H<)GmJ7Q4;RnV0%=VlOV*JKN4-jjepLH~|-yMz&d)k$B*UlKho4C4nAo?^n9p zk9rm5tPrYM!hLhZrMaOzD&BHZPRWC#`p%c}?*-)$;q4OCLLvB(umkO%AeV**?{t$$ z^zJE|kRFI|9*(HKy>mIW2-_~w>)C$Goii(r$)q$S zam>|h3sRUTm5%hMcnvxh)ACjpI9BOSXnV}@~Cml$F)$Q9j zWFEH}B)AJucgl&@bKNepe$&4m1JMXJ%h9RUNS=ACFt-X2p0`eK5fM^ebeysck*cY@ zd$8@?9zHYSmbpWKK0~{M3YX z3cPW~D*cae3uZrep_(Cf1za9g6-3D!@zecpKJ&~hcPr{=D0^k^g8-DY{eFB=O!UxAnAsqwn z*+*bL@udA;i3-@<3Q=`MsPsG^-JFU<=EmRSqGsa*;)~P9%DyGvq)(28u~}+!lL`)QFTvmbhkYm<#L^A z>RPSHzuxtl=>NN$UB%0R0WbV&X;Kam7M-zx9D3zUYgKg@Z4rhNAnHuuQsBRZ$7v@& z(Kc$^3j<+MO3*4kOo|6y20T{k@9F0N9K?I&fsU?|(cf>oCt93?v+7CYaxjYwke1sZ zs+Zw}`QpG zt-i?~En&sz8_+u%?_ST8!o+BB#!F!)y8kVrP6^cBan%Z{Dp?O*bDiq~jf75g7kOW! z&Ht^>PQ&Zg52F?!4laxM_m}_8b=WGv5wURDGZC{YpGaugJ$r_ zxONpCHhWnM#ouPW{|!YdSpXP{#+G6qx0t*d&(V+Xh(HKb0?lrwxL^fEL}Kz1MfnTX z3vz)9P9ks0NQ4cbT)Z-B*b8E-DV@?u^XQ|-mb}T%P#VsU(Cyz99Q51xp2u1RqLT{; zRD&deYKF{UJ>9$1#svtBfy#D~AQxQC*pNpPRKru?YNI-``rO!{BXFMd!zdW{<={5R zv&FDuacgr!UvDuok>{zXG`wKs-+Cd>FHs-ilF_|TwrOEeXSUcBks#yx#KH_3MC8m5 zAlYT&eye13JHwIDE$UQjHS%G3_yF8hnjn?vPuZK2ZYcO0P&QBab6|vS(ADbS9h23* zsW=(aIRA6PweY}Gzu;m*=k*8JlZy_SDX?@mjan>ej;w8(g@TT-Ve0#X=wthCvHgUJ zEupRL%pXM`HID(A?0GWCOb^5+o34w{WIueumfCHSEn=!LQ3N z{q!c_aK8=+@ujdZKmOH1_ul;B_8=xUeD$hbLmf|Di_`Uoufs zTP)Gz6T*@=$TF)VF`4%rAf3mzd}=58&J2vn=AIazN zyhvyM>flRAl_4I#dnMH8de>0x^;eTPqBRXs`Qyds%EtO38^UHptsps#F z)sFW^5PO|OVoR6j3>I$#-ut@#lL26ak|#5@MGZhq(ztDX&58;?b+PW*>| z*xs3PMJEBl=ID0253TjT#h=2gcFk21C>-UN$hR(*@xlq_lGaX59*_PaBHm;V#zeYV zWr9G#`UrAvRb+yQDh<>jE%F0 z{U&K!6UrLLRE=sB70dD~8eQ6`R{YSPg@#jJwKdm(S8(X1t_azCcZ*xw@^syftpq8j znz+0)t*>bGW@XeK(3@rkK-Q`7e50Uc@|>l`!nL;r(>Ahxb$7qDek*pPjfR=iRZ?GC z70Og2Kbbhb9uP=)j)vCe7YsS@!!~Jux5By@cU4#3vYwuOse(4wa{bkl;|0QOv~O%f zW+kYp$o@r2PYP*4?nW(O7UKc(`2)a5Uw6y2dbZ_lZ2;@|4CjJlKY37PG1kJD;k?v` zEwi=a^lo3T!3!LXrL!~71x|OA^`u#u4;SOJdR24+3FEzH7Z1ihVP_B1Yr*uRVG|lF z0~ug^pb{I22KXFZNq)oilYi%GU9P(Zy15W!CsWcE%T+91Tj^HRnl(OT#Wu-=8MZC| z>}qLb$YTofSCYq$utsT#^!XB2fc;#kTP-UUb-+vszVa9e6p;8!n;eeyD#DMb=^v3N z;FKz_P8u$uY{qI->r14oiYtpVh$0>$QB~<)&Ei3nTE5K_kFxib<+;o={6Y5R9kng)e0q+-d(7U z(jsZaUbQqEL#z?nDrUOqsv3qaYDvUW%Sk0d)u6Rht-+C4qEty#k*EmwKRU0U7ti(F zd6(_F&iS4H`7Ph?=bST0_0ROM*U{^Y@N{X7U_aEU$^*G3N@}n6giyfK{td%PQzE@w z&1(YzW?GQV&-q6%XxZt|6cNj_PIxVthGznyqWEGZgLVzhv@}%f)zIKK(_PIsorgHs za1YWRL}#wOu-f8mJKRvtT&ODIsjg6Bt4lL?K*F&1_jZZa8QHGJmsp^#412w%Of>f8 zif=|2s{xKp78Ux+Du5kczC*n%(~ZWe?RBMb)~KfoE%&NHvY{ua29zHkdp|(f5kMR2fv@0eYcYc;~z`8 z;mDy@s6jXyfJ)t*(H~#>Vy4{?uy1b8MONzH4kPg9mAUihm{Q39_~MCCv6tH~<*!d@ zOD3>uR9z@KM0vV?O^C?;hk)|l_TNFF295E|u7$kkg5AqbXKp*ShgYLq0)a9p-AY+L z{EsZyKE4{0PYIwZf2W=PC0FMv+kJCH`V$}iERq;t`+sW237&kKeKOOQ8|s%~aobu& ze&mj7#Y##%qe3UFtbu2V*Kr8yAE%1B|&#IbD0&PEn zc&zdz!&$+NtwsB;Y~JUK@(KlZ-OVe4W@+$YfL5 z&8K(HPRmsk-6@l)`vPZ7!pE2+_>47HEJj{MlALSWKE$E45YgcgeGdg`&tYHKQ-p>S zq)OEhE>3}*n;ZTtUOgB`dqJ5r{vnf;=Y6604XGv=D&+1+D9V$)N0^ij|z z2`VrT%1%_BwIH61<+&DV`@)plLveyOm@E1!@3z;h zSw~qZ;c1o$3viU63pu+}kQ<}}Hwy;Upv-i!w+X(Yavlo|Qv|!%_T$mK0DW<4wk)wc zcloPsS6pwFJubG)u+f|=5aURSu&38*<8kFFxUt3k+0ZkUNH59PH_+$Y&$8P95d$qd zy%lO+ED2b_o+?brG8{vC_BHm9F0yDF8}Jz)Jc5}1E_skTIkeX?b~U@L*;DQJ9q}8I zocKSmezIMl7VE$@f#M3PG|ou`p2f0cG*XbFDBtlR4ABzrZAo>-t}byZ^0I$G4{7OF zRu6MRP2by4FI)$X6V}>1Dwp>Ep2qX(Rn~k^dsQpeLH_48gH!11!Z#0^#eU=Ur5kQ; z#3uDDntCSWD8hQ(;^X7pxtovscef^hT$btA(NRCkwh=vE{bO|>XvR%Pl^GL%TZfPq zeJ}~f-TafjVxst)7?Do_u!lHuANASM>*mI*ua{%o%Z^`W>oZI8ZYLVn9{Lf=0f1s> zKZ3nEQTXU{MrYFxN`PKKR?rr8>?=w)Ol#0~_9iI4ylFQ^6%lOQs9mDTbkoglO3L4+ zE3&!9_8w!*&Lwir^M+Z_1^j^PDH?~ed15IF_ELu;TZ~)a@K&83K#@Ky`Iw2Xod>E0-S$u)gD~v}>(26dU0Ulw=-v0fSlwbSR*> zP`uI-p0i&d#@uKtl=A4|0o166JqvjCm(ZZMK-nO=gJQOQ33V!qJGn?Nn!jgn6*p-> z22H@#$?L*L=|+!IRR5O!fD#I=xiy-HAE!WiaTs)_^p# z)g@VT7Zh9gS0vfL@o?P6cJk5cL*NW789wer`d;8*siZ1I*>2zQn6yIKZgIO2Y zU*e_(KEZx9eKcl_gO}@KbLj(HOMgr8sm_Q?8&Fquo1J}cLL?SsBlJ+ zz%f>FK$%XN4?b(&DaIu*$1fe}6+|51@J*b0dUMdB1Z>B}OeI?9v3w?i-We_V>__lX`Z{e)Q zPFquj)X3G?Ai!WOL@`~wE&biF!%(hZxBt!r0+cEaT3<gV`pFXVzoxZ*?w}^(bLl z!|D-tNDeV0G~z$$vw@YNd9(Ihn2iwhHJ1<-=yPSo+h2a?%ZJFX+DkOpHWks9_fY|2 zYWi{*U~E`DRt#Wh#d(JOu<`RF!>qw>pPARta6nze(4OOy&QeJdnCh($QRI9-h{Ck| zn-^GuF0V4VtsG%dOfhoVP%x;Y2PR?yy$@vM!ig6eyD}{F&%8oS7`r^#ZNe9)h7o|&fn$NJCmk^iyG?hyq{91T-?1+~b!^nOP3j_!>3wgZwcRb?EdrtSSP zaDfskb-%>5m_R=WCNpX6=9-#2AtwjXL!5a>bcZfyO24!Dqxknjlc~B&LZi`C)$}ll zFKp}!->ZDk)3rU!J4CWz6<7UY<{W^Cay7fUtWQs?lrJ=vY_KZ@UJh>NHBy;heMmc+ zUEDH|wZy)KtT=NlPlLyq^K;`SU<^2e`9|R~+$%aB43;Ue527 z?^0-de!ka{N9`1`-;czY!s&#StB`bHP zRm@K9oa5K#X&a>IPcCFjOI{wPIrK3iX*?>sUosd}a3FrWe9snk@}hd7RGfQZA&zp% zO(*xqMLOe_Qi_t5p#zTF%-Zjh#6Bn44Ci9`w7cr2Ptg{4D5ifYzu-N&XTMX+l{D<% za-o}T@Kchzg+~jPGiEq}?<`Qt6%PCRiXIbcJgIN0Oual}e80{5l0PJQcvoo{b^@Gx zsVlm{xUXeM`DQLPf#!zU zNC16c*)=}97xwut zn_Py={T!VXx+h0XV~JIyD)s2IQx{IWiCB=4$b}2Dpad|z$LF(lZ4tfrod_c*A^!RD zb1gu>0>%N6YC&q>!)i^|&!<;Hp)3oEM z9T#3tsX}KEW*!y7{hE$Qi)OWcH7)c+;^2z;k4eQ?jF!>l94~9LP>~-~@vA1OuKFPU zd`zN{)gv>U{&mK*ybhZ9(fS~*F<9nIiuKIywhU!An8}PKwJ#?X9n53^WS;%yLbN<% zT=8x;*aVBBMto9xgRGx$ht398LEE-G29H$WHcYu6kwIz@;91V@GArt6gWsW!R^K{r23~k^LG~b z__#HK8?pPlsm6Qe^-UbcJR7}?^D|ckQ-bw zEc~yTfQ?>LQvz>;;&&D|sm(QJeoyP}*M-%;lRTQB;MVo>pDa+eLDHd->FAG1NvNo^ zlc8;R`NyxP-{Dk4opMMOa9Ju0Ad6a=J3r3pxp79fyF6BX%AYLqHcBE5zP zsC1AZASDSMLLh-a5+Ln{*Z24Rzt+7U?p^DCI4g&fa}IkyGkf;TGc$Snz~uh%V;7Eb zaBv*g*V8fM;NZlu57{G!*;gvxCylW`4!YhkzQe&$mB3AZdWik^Q6D{PKMsx)9s9?D zv)2q>u`izX*M017?(O0adg|-Uao^Y3*~{;_x4(nM5%wdjRDGR0kAfW57&JepmymJl zvT5R*+sEWicVE2nMenUydihD5hlSky?wyp<%f^o+B`;an_bTT-ZPTwi`^@cI{SC*9 z@tX3}7w&w>oH0m1e(T>6O#D_g`ScDSSHn$i&u?A_7Hi)c!|m(A<1JHodpH&w0v%lU z(^^JVOnp||3VjqX@L6`5q*`JM8{f4XL|$bNn1kb^EZu{^_wVV9%SqIM{j(LmDF1)2 z>>U&n-amPzbw`hD|Ky|T|9=Yy$G3_R`eo$ zR!d<45VU(6La>4k=Az>+{eAb|*fVNf$?lo1``8J7G+F`l8b`_Z{)%QrYA7x@2c&Oa>jCx#v&2>M0c~HIzO3z z9$!l2;$6?KtlJo^`4UQ2My{IV6aUkUhRF=bydep|La?lvxuSGXhYzy_Nd)y#MWAqc znJit3x*isncw+y(D}pda^iVGah)pN4tkaj^is%f#uys5z1;FBiIxxGjd*UcUE&C#l zCIzs##W}(tLrLT448VT_V{32!GUV!*f7nXP>xC8;m6$He{K=1QaL9y18Fr_Gsw#l1u@d$fmvlUv9Dh1p->*t}^VA`a0waxo3b5@qFO%>0e#KKs*ySywq z^uq_3)@$l(;|gZXy}#N&{TaJgflUT%XhScaN?nf`^I~R&(H;yvZw$*T@IG3^$37~VK6M$0xq5Ly+ zw+yHxUez+ILfphMyP+Ng7~~Xm%a!T!ECek=29~#^G%5XEo8RJswKm|2 zCSS@#)oE4V{X>H3T+k(ek3@jy|EBtBVC+8iKHsOtj4tFJeU}Jjj$-NV&(siFT8}){ z{u`+{1@c1n)N61sePM`Is9u^Ewyum!|KK2-Py}dMFj=*+yQ2s1!>mQ6x)Zk2fBI#L zV$)ONS)c&J!|yDXjl=F`ybLvrpCWL-93bWQXJivbMBz)}{jx&c616|~A+PK~Qn#^& zQL|nNfNcVAQ;KRstO9sEX$BA_bp)3+LUnctwMF^uWu|77%!@JWqqf_{1f(pl$d&+& z^@w`wo)$KQ5yqQ;6=&vHC{qeX42~k-yhdaQW{6B^Zou01O!-ELlpQJ72D~w)$=8Yx zrCVs3m6(Ze5@fgp>s}SLxbj&?*-Kv!hE-3DnddVrcj?+LJBqUiZVWYyko^~kZ)bN# zB%o@iBDO@dv5J?Gq($IM3BRX6+TQpAH55zK@0TEMN<#^@(>-=gQrtLHX>aGIZt&#S zJP$5Rw8%W{hNJ2L27bBF1N3U@bm-B4HLvm;)PF}R6z96w0Hu1H_DkV6I`Ge=&aJRWktJh&)U1o2h_Z$0t0w6 z$D$8dF_r(6`Xv@eg9o`_XR9)#pB`HUXNwx;SeRlW( zhxxB~)>rg$`n?n@?(&uYVk>8-rU;Yt?(g}^%G`Bz#o(>Q5MkHBeIvLj!F>@6)c{no zkF;ASKv_d{8llS^QHD&xk`c(hgG7KO!;#Qe+BUzTetN4fB=ijgXLSLk_(AlXgi{?V znKGp)ASF_C*p}}Vx2>7opHzd+W1n)b9SFBJcws7t>0);Cp^vz&rnFM97nWDo3Nn?$GiCK>-5*s~hcdl9S#Pn{_X zSFiXHt_4uiN|FN}rxa}BU}e)0WQfdS3)M+h`bWuYfA8r7|LohmR}NwGu$`YeM@+!~ zns8a@W(GPzLW7}hYMc^8tNDR6Tbqnw;DM~>e$8CNe&zLBJGqgBF8K7>7=OSKUX$)W zJ6Wwgy)RrI)T_Rf3gsjtR0T#RryrR2au;NZJ&--ZGYu6M4XUtDoBRFl>|I;4CP40m zTJt7jlE+jjKd+f~b14pTF|9Uf#-!dkC=mE;LPfkV8~47ElY|TD@4-yfezi->FOBB4 z`#9ZS-}C&yr_*AL{#1N!HE`r#cZ%2Ec7LIT2ylg%gTTP zPHohPAUAe_J^)BjrB-3~6O~jEHO>nMODI>w3&3Hu>*IKuTqYG#ffLbpV^$Ol%4#Tw zHzp~)vKLVboI2BFq9cbg^qa63PEMuvcWb4C;wVh^|a)A4%e z#tj*puGm!D22Vb2+@07%e*xYSm=M%I_=H-uQ^Jo}+Hm6hF6#PvA)X?D+F?IyrlRa}hrsvz5+Km(X zleR`GNaR&RZq;^qV*@>2!cp(>pC!@$_UXUd7G8r+i7Vmy6Duo@6+4c2BU&Zo!4B8F z)&_cVGaed@Q{Am1f9dvCOw}LN4zV>c@RLJ=voJ;f`b54w#N!hGd}aKCECR?ZdMd5z z17N2UdULa>yh~Y=c6E2oJ9Ic#XN4QM8$oXa?9xud{6rh13O%H~e=ScbfQO!waxc8{ zynrgW;BdTSm&mUg*y-|-VRI}}yV^$8HMQU7o}cN?=LxV}Ax-+|>B#mUqHmw%oI)9| z2mQH>xFSm!>~Z*I*;XYh4+2KREeKs6KV%uIoiZPmm(uq9_q-XB@`>T*+#l;`0 zaO%~1*Am{CDt>GE=t{fe5|_(@6p;2#z4RB124LCE$rI+6q3g@&1p87c9^8e~b%#|A zUK9`cOqcQC;{?b!Q^zgMjgzsJn^`b<1mev-ehU%n8z2`i%^Srq=QHEHg zFxPPXIU-rTin(T)LLF3>Y-Ehfnt7?>J)i4|3MH$99ga8GKhoRw*!Le_$y{ab=v?C9 z;yu2B-2MUd1)Sc~CNdw)$s@G<6C2^Iv2nEi>$Y9fFuytZc5SYBywXXuv%R&RDepqh zjF&&2x<)A)d-8$GtZf@@U+<>h6rL8TT+Yc8v@Bq2TVmdee2j&c9@V`?)Dl5Hn$^rz z+tcDUmsj7)FWFFw`*WJJE13W8O2+>Bn9*Ravv63GsF|6~btq#B-4MgvNnmY$rw!3| z#*iBonRghT49_`6yEbhY*udT=f{mxLxvCd16r;!|gDV7yqK6Xi-Tw@UywnIt^+k~X zJZhD!AA2?AH1K;=x_oseaNgDoWBl5mRjaKdk;mVSVM^2b#6EMUOF=3oCE9C$W2 zXU(`|I}&-jDZrMfqes1uGHt07+83kKPCBXK^4+gmkYy^}WS4HGMQlT>&`V<8Qi0o> zJNHFg50lw@b7~M$tCqrQw!fpt>uy%F8m@a`=-hlkzDEV6AWTw5Bax&pSJ46 zy&k5&LB(-4$)oU$HUuqDLc0J8AUb$;j!BpA;T1LHvUqUqVJKJ8zE5GIL8ET^j6#9} z@AwkKuiD&CyWW(xhYh<}#ywau^<%rpy}E_`{TA|cCqH6 zMo~|~Qkf0OG|Pfb!?^EYS=tWJofWGtI1gubBC~?vT5K^xYiMIqAY39wYdX1VG4<+AH_ig}rO)xGn@#1W?79jJz`@5; z&>df1UNz-^&9<2C;|}^SgKb`SE()jhL~~Vdjh*Ocf=%JpSP%oBevbLuN4 z_>hMT*0yQ4xdLRVr_9*0a+=Yw-;e(|LaVi?c$i_-ll3izA9Bx+V7qA5wk`FR>M%NA z!gSs{LP8QvFW(P=Zl=giH`q5B#{3PHWS+5IKS!}001e2Lr%IFR;81B$VpCaAZCm1t zbUNGn3;zR#bb(kWsM6yRf8F24Q`na~!c`aPd!ns@*h|oz4PJ@6WD5Wj&32m?@xTPC zDJXkfmWliE2R|PDzh`pcflfi*Dm)#?y&_;70aw z(uJvu9{+`H(;rx?F)S&*2q+7-%cxpL(nn?ch|D%@?vask^3FIC4^*yOuK#$Bm7NDQ zU)#m&{O9nVuh0}li>6f|o6mxoGb}Z|gE%~d&do+Wx_4I|(&T@B z=^hiwU{u+{88*w~{R|ZPBtuMuZ8CKV5XcIov2Z^@?bP2eQ+ZVx$;>82!gkv?h)7BT z)8>)}^m9yD)oo%%WdoF!_&*1hS_Fqk(pgLR0i7V`g9I#10^+?Y7k2IMf4mLcT>_8? z-fqyvL}A2GjC~>R>;J+FDd>zWD_qBi{m>>r$tw$sJ@ePq{s<4H@M}r^4S{Y0sgC>M zLkxh{Ntg?L@ZW2(yGSURmA=2kj-bZLANEqrNtw`10njZimH*x%8^(@(u47+r3zMdh zw1$1*X)(7%_l6e7+t^|Cn)iS4^RMxJrAh%qH}iNP%TF#n0WR(DdW%FwR-Sr`pzeQY zA4Bdf0@GLvqtHu88Vv%vKb|Nk`G@iIV+VF-}IQap)^U2O|(CwJ9{Aa)Lnd|LS%`kd<`078+S zcJ(${Mrfcb45q@EcL$xk15GFw2wO=m!4KbAP^~S}<~qU^&?U0^%gQ&kq*KiI9;c2X z9LDM->umbMP{ZlU33=W6_py+RTR5qGT8g9F$61UaMa1?sKxkE=Q#5#^Y_ylLp4Ix7 zwKWm)Nr#r_YkjD-oEz)8P4FnMONIBh@OtwT?~Kw-=DmFtc?%zFbtV7RhMDQgYlTo< z$QljG9`pixyi6wa`a>humEbJ~Kn6=%?;=%Tsn)xYumn*QfHhKLwnK5;P4{NK+!cka zNXXya%UC2L=N+?v9^W=UdOUD_jXzK=a3~btm)Q`Y|;>xZodTy zJA?5r+g;BO^T&O}{IN})n@u|7N-Yx6no3VWpEXa>tf4=q7+5~{YE35}s+i47>8J^l zbc))(=WM=YY`l|m=KAoVSMzh4lIxzmsB-FLr@JpMh5yiMwQ|dqE+%lemY*>M>&2{n z=6S#3=RwMsM3t`hWYqz}W!SS;>cVjH7`{*8bLbjvul`fx{6hV9oSq6BGjz@TN*8n&NzV)s*%xVO@| z0&4DyJ|7#sgs?X0m>+3hRT(c|>K!`^b(?}0`LOC5Gp;9#*)M!;yjGlV=fN~2GF(la zU7y;zFKJIG;>ZX^V$EMW)|e`F6o>Su3+$$glJaK&yPq7b0nFB2mMg2HN;GfOYQg)U zB5oae1CQNGSj>pXVE!l#H8jv;NdV47c@F_tv!WU7<8pQvt4|pq!$O;`vf7^gLu-Hx zmC_%}w@fga?5-BFz5EyRxzG962d9h$wz5+juJbz8oz`96!_AB&JMG;h~E z{MX#t{X84B4NMuwZZ#}Wy{r?6rP&-Jyf~yJ;M}%8NIPV!hE#E(8M+JWWo>A}lE}o} z_d@hF-Mh`pQb>9%X=#Yrcm@;Y*Z86Dpnt^?*|^?sGY_`UPo$@$CSrolMY%{6_9cl{ z+me=&L~~%d4%&K9*`k-ScKGT;Bk$g_BZxt1)ot#pHjw{~W>I@jcD!gN#@E!ajWq=j zheIbkDeJ-X$`h+cS&E{Y`cuGmX@%J|5So&&?@EC2@Qi zo&-$Dm9oqM^pGG55k9{ZnW;o^Uh*QzUud@KY+v+m9{Q2Jn5kj^@#?=!Y-LB0cJpB; zkPhhhG9J1$9wMqjh#3O-*oEk^pbIo)r=SACwv8b_OdG;q_iDF9CkKOcs9%ww(3!@P zqO|_-`LPW1fBXpFULvCXY3E+x7f1dyuhzQudyL36Z4MGgAXgV#FyCIkMdP{w&a|6%R zIlg)RR6WY^El^hsA-NbWCUD+gM0}+Bkw)UYOBdsn9=@*p#EG80r@bD*SwyE2GZ1Vb zLk^Co-FeZQjUM+MywX~0xfssFK`3M+>|)@;|tBdEj8GFiuc*p?IrJ- zs4L`yixHDCwsIOOVntb75!MZC>Pqn_g17TiK-CJ)C>DSm&5=9A0mz zhH39b5Au8IHTWLp2(_tHDlB21uP>@^xWpOB<^vDU67p?Gb6#VigUij3leV%%@{gl^ zi?wXpP4BP^wZdjT{Skq;=k{!_j%^jT<5Pp^xp%g5=UP5IY0}XnVm+t4rw)AU%AfLf zMn-KHmZ<}GPBy2>bIgp84%}@f0b%HjdpoICQi3!+yj~z-sORgb9fZl`QysfLJeG8( zB-wa1awuC=g;5Z8eKF3BNRD2{(9M<>85gyZdi$iUFYp#CUzZo;GV`mpUrKO&(JZZc zV{fZYwCd~&!+|_(cTPFMqT&~xWGZ)zXqJ@+S{S%jYv(3mkn3X6`{Qh;P!ACKXdPsB zUMTqrV5bgSS)?FN?VKfeu!+Q5?JAGqWRlxzNZkoo_v+g7$6AhkwxkY+k3Yk2;1po0 z(z5hLeGSq1b=R^qdDR>7HUlJSYccc$)xYU_+{fR3^%Vd_$!z?3DG^7z&sT9Od8%hZ z!e0;#y%b|2&#|RiQ(^17^ZW;pZA2B|#nIdKLi`d=Pc({nI6mIbL_*sZZVfCm^Ag~C zn?>Z7lXOT3SJi_q`q;|LY1Jbx!YyG{iz~iuC;4-bLO)=HAf#%KrL|<&lo#GT2qs@5 zS;uKj&5+$OHk4Wpw2)OX)w`wfrUl8bEvHm>>4$;lqR;^jpX{)Yi6RQRHIOIhnd#DA z?RD-jDDVW{*sX4GVPQR7qZPTX48-fT1Y8H3)a=!>`kWv$N_pLwj@oj9us&iU`Ccc> zEnxXWb(l;jnKfz{@zVD+H9e!WX#8sp@c8zr z(zL5iPkaVpK=akKuB9!A>T@p3U}18`y&}XK#0#CH{NPzC#4wiOn(b))iFJ{QYKABSW!2uBHw>+9OU_2iC!u&ky{F z29qv5UK>=mW|Lf*kDpsS9NGJPgkDVU<62UMpF?JRbBo^I@H0`4)zRa%x!lOl!S?Ny zAa}$OYjnAH>jxdMTT#sq2 zinB5s>OVKJwRyKe@M9>UHG-;cHK_Rzi=S~--MW0mxw(fgdM23h6q*yHB^7m_p7QE( zO3Q+r%Ybrw)Nc{YvWLc2$I}pbKVqS{1K-@%c-hIEX(t8l1cw^;tB-z7Lx@elSeO#j zN~17l(W&9RUX;JAiiGXa=Y3qBa-!?v*3N5V8z0UcX+{_cJl^tke-eRHtSR4nwj-f5_1@ev*B#ib1)?cM-!lu8a$iZ8wE$}92 zj9GEE#={MN_2HgXspVjA6P}2xI}X6j9gWjl6`tT(J6cbs7LM6!G-E0QOvdt{f6v?> z7@BuZ1fgE;CW`!?YjHg2WOx+kg2A8<^}qdCI$-j8o7~XjIj1?PS!=m5Hp=tL$=xX* zmu(Y>99w)qJ>YSL4N5?GVx@C{>--%`H-*E;q^Ya4*3tau=JY)CHLdG~Io~?@A+Lj6 z-5P}Z%9d?n4bSx|p|`<{@-S+PX6AfgDsLcYn|>d{Qn z%gmrgen8RfmOoilgWU*T{{X$kG=sD%-27xsYG1df!j$J|`w5c(P+Kt^Xan3#eFgj3 zV$~e*@JCKg;{b`_vvaLUv$j8AN_PN_(1P|%?p#b%8$jdlh%&_`ofQ~{2E4dgrBO)a zaWwzj0JSvR)P?h^rfBUuexQ+_~@WVg7Dh0MZjiw}8gPR7>BTE%@m$Vie?uCTa zykX+0|Jf9!T}SUi5p(p_8OVB*1CJ7N#BzlCwIvZ08pqp_nQ9lmwiW&8sV9QkwDMTE zE?y1^t7^v&)>LXnZI?p>xHuB!zP<}*ru1pA*Q)=Dl;+0qD)QUii$*T z<{jI7t)ceN9NQv)^?hjgQRau^x3GeODkhw8*1TI;HuEV?O!HJL{Z5A^uvq3PsQsu8 z+FNAhMgurvPP#_@LmW^%Pk<82>|P;U^v3K}_GI6brip1TK6}-m!7r>rP!Q=iE_>y$ zXYCrjy>hA3=;^>w90bPN^i;)}*}|GUBgfNu3(YPB?5%hR#2J+4^GlbCdV$$$Lw+J8sH)+Q94e!qCCZAN&=N(yd#67m6DnOHA0vCNHY zonPsE$Nc#-do0@x3za_0u#dA()f#GU?!u`wbfA#9^DjvR6VSOdqsD)|!QeD-eMMlRlI^ z*lALM>DfLlce8av2tC&Cy~J3%O}J4q9WfyAK<2Y>H}a6}O_sE3eRWw=nEhnfkfZP2 zW^^b<_*DhjWUMZDcC9#d!1HA*!^+#UVCq(Cjc26GcF2?>6|>R|&$K;O^g@}aQ{H9! z)!C~dH3b0mpTXE%T)3?W2||Hr4-enRIKoW0+JgWX(ppd5BEd6f&u_)>wYK{Hp{?b<@4Vu|njAgZ$3L zM|k}h{-CM4NS|Lw9|uAVd23J0gVB}Vun=uAGf|L2tLqD9Y&S=3`&{s1({=mV{VEFb zVWyo!3gS!HYD$AA!X<&ApHI4XbMX8j>>A%@n8y-3cJPP0U8#plGZtj0EqASyI4+tK zyge{gJ@op);K-azZ1Y*kHY1w-5ifG4uN|c&m3;cHd4~9Ws95ayA<5ty$M^bN#~xE_ zD{)=8+wQ8gipigJ?)iZR+iC^pT)=yyK2(9YTQSRylf$b@>e$~Xd8YdR8}a`CLAd;X z|CUNUi+7Q>zH3^?L$8fW3tY2Ay8<)^I5UANiN&O~LY9?9P{ipl0kqMi~>aLxZgf$V>U{ZEWm*C+WDe3sH1lzuZ z#f>jYG&XA%Qg_`twxCZ-^sw}PJa`>jMwJgkFNyInW`A?egBb$9vF->8bdL9w8 z-Rg^z9enxSnza*RNBIz-+MryxEL?`|8|oRILKBF?Ly0M#6t|@ipdIsQ}f06h=Zx#<08m4$)10}|IWI(Mk-QW{L z=VdquO?*hKdZtKj@lA97V=;86Xgo0wC=+&tsxnvEbtS<%!{0+Y#7khx#;gfu-^R}} z$>|x1R-NGf2jXdam7CZ~v>&2DpyK<)R!rXGI0H%fIQR3zHk6|RBG#$7DHoGfBwFLf ztF;ubcg`2cwQlHiG`P)Z246DVqc@IiYo*Uqhnykq*UFztx7M0gVGP}zj4?W+R~>Fo z2DwH&Z>g6pW7fVdQ7SrZDR9;F+j`2g<90tfllWLhSZIepsX1)DUMqpj$SfYv@r@c4Aejq9n0Wck0H= zYQjM?G=PCSu@dN+(>oIFCUE}uxg#TT)fp8aRbC-UI+-1&YA{X}yc#HXo<{K%K5l=(!E{SSp#8_q)n#vZ~ z`L<#61a~lFX7S>)dnFb3iCs5rLsZEdh|2XoVNHkkrrl1nw*!x{`34#!x+~-3n96dC zk6liB?mNN=q%VHI?5Z_qi=pH@Mhoq7Kbz`ih&i*|Iwog>F*p6bMrn(MN`#VUzz;GI z(OhOnD@mE_jK_IeHVU+zZ!@)Lu#*`aj77Pw%7@mIVMJlsDGN!HA0;&kb?r~h;~RQ_Q;8(UF@MPgss+*1k;e|H|xBaSYi&j z?OT5=O1LRXntrNIjpKUNk4wvzqJ$Bd%zy zJvrSsybz|e5=lzEWF;G9bwUV!4?uG zjX`ykBe9y7*fl5)-K4&N(1(_wghGMCBCd?nv?PA5){~*vui)=SpsMkbg(XJg^RF8l z9qxvVHF-D4ol#BB$L3!wCL0i<_+$Kq^S_;Plr_DlH-7RA7U~b{eohdv1(evGUgQr$ zI(n^u!JiT_c(o?BfM^aLDQiIuC(vA|HnbYN%k!c zy|M5wR+QSvm~o*?hNRfsA`9!3(G0}#!esT8cEu)5PX7g57tG${pD>u2HMAx)1&6_sG4RrLc-Jb%mS5zl?%n6H+mmnfr3s0rgE(ij)MHb9DSZL?fA@Ux6DTUwm3PiG9s>_f0u zBA6{zO^C|yBoYPQdNEm>Uu{C@BJ{M;CO*7Bx#ZR}TW}U`?N-i%YN!ME8x5)-<6WAT zco>KYxeVavx4)^MQnPLbF*K?PV7=WTf%!S7aR;5#>Y4Se0eY?J)yMOxmm9oY9+30i z+zsjV*YtW58!HX`sSqz(1T54`|0Ec1KGyZTC$}rLlLvfe(~NPWMat44 z%jF>7uuw07E<1&Narpw@1QDTozUq)9F=unTeb86WhkCgz=C z7j$iY9TiffI;k#x$jkxxvlA3&%HnF+GAMCYu|@SXQSbm0XIE=3wGTHr&)rzhbLW)}emSoC3%|^8(R}L`L#*PWeMl$!6!M^N zjX9OHUQJQ^9C70P*9?d{4|sBqwH+=}eOR;me2{KKfV25kMz~0Xlvy)pmhk3HtzWu( z-}u}(ZC9e?4+lI)Dle)j5sn|cwRKJP%V*`4$P-`k@k$cBoi4Ex_@uTMOv+I%*albS z=ds0K7e0z*wfTM2TvjWT1t}P7ZgiPCC3BWH0uF|ptbslv$9iOOMRR?vB~h1lANA>Y z|8V40c-klQb>VI6k;C}&!;HFycC{Dl4IVDv|CrEn&vZa++ryPzU%fBCb1y{rVnMTW zZ=*Hjq%a2`*Vy)fsMC=V^u-Y)U;WdwH;^G|$qCc_lGw^%UL z&~R%$&1p7(^yk7a7bHlud$lou$A8Z|yRBkU;W=7(L4vnf| zqVcXjTpuGIsyA68t9WN5SOoSAsj687t7tuKld$ZGvDcSxu*c|!_L9Iz{bAi> zU=cUGcb{#{g2yJa8l#JU-emF&B=+2}=n3N|9-{P&jMSP)&;0808;33H^JbC<#iaz) zpT5|gW@vlc20`!sl*{UAc0NxWCz6qh$gMHgyUjA(Q)bPA46p2$;_vP=X?2+do$*Ak zHf_sHe|OUkxt?5y{C$6|GJ6Lz*>y^}uxqTK%Q5{5JSVx&1$gEcHp~Mt2`~EP2lLOh zWrD;u5qQPIum|hyVQ4$~d37RdmN25<9QbDDlf{=N== z5W{W>I5s<6EMAe`qK&f zG3AT(#cq&S=x-MQM}EN6(@7W z?7vRo%(F5?Im3pu0vDh%Z2*<7oz#>AMC>-nP+e&X|3O*BhDSL%lv;PecZP=p6CxP=7(e*Y};neFM75 z9|e0eQ;Dm3Lm}K%saQyb+r)W;-)prVT*JB*rN+Teb6?!s%1jqPe61H;kIY;?e?U2E zV$ve`Gr#jd^g@?!(D}N2gV6B~D!A_$k-_$q-DsQS!upTu6SB{h9>wB};$U z_UE!EKkE&58MWHYE%ZAnz>3sg!8{4@ZgbWJkJUX}(wG>z&IfSp`r&-dTT0Ee9nFa{ zjkghREnepHqtZo$^@BTYN@kv|q&jf4O32ce5mko8&LjwLK?@gEf1KObT*@po)8UrW zLh2{bryYw&>e(}7pvW8Hl2)SOSHj|Ic=>B}5Zh;(tGx$;-DpeUpA8($bgWHklF)ts;U3Ltw1O z!m=ZQj=ps9+V_04|pBP&UTtMNN!g9Rl7blZ4=_xAEuE*b4HT@;CB#J*76BljX*B>DAg z0Mx$u_4W>=NO7Z-YpgaA65g(cs+ICsQuleDasSz#Wli4q?Rn#Z2yXo*PN&CH4w3!u zk-Q$(U{i@~iOltx@fSKoZVbL5XPEehF>VIe*x*tdzRB-d(z-atP{3e^rnHJsIsK2V zocNwisWeSjxmfIBT4`d-Y2e8O=k7_U{NdmFmC#zCKU*GaM4e}uqg)I|k%17@&j!irUqTVJ}oVw0|fGe51B)>a9zhHRr+E&{pnu)&u1Sw#C~Tz6I}B zn;#Z8T~qW+`{}_vFZ#aym`wJT#1w%jdk{LwSCsM{^ogtc&q(-Qql?iK1oE6?t=Pz>Hp+D%`mm93Pn%djoRH9F|W z-wjtE_}JtySbe3E&Ek8pJQ=LJ_{6&DVY-oYWmCuJDao+!<|Djcil?6ZP}i^Y3J!hT0G~X^Ph03f%B;@rJbn9aYyh_cM*|1ec4k`ZiQah1!!rF^a6~yH%79q(^!S@o ztX5qQ%zzK=jzyf{Fe=s*FzsxZ^PyRyld!L?r2$_vrgE`h$pNoEeQ`*5S268d=MCfFSXK7Xh2dW@s&I zdrfNLtuJbbzs&b^z02o5Oh^6iF9`@2116Z1t}YOmzg{qq8$mlN@x5M`R}okGX&}Rl z5V%G55%5c}!f~!Htn(9Ieh;W@FJC*5K3F&8DymKbWK4^$E&8=+2{i3PH)O@0a(_Y& z@$vJp20ld`TOU6uTS&Uq&`K3ceTsRfPltMk$L_rn)6_Z=C2;YQrQ_#2`0#R>@1|eO zN-7k+EK`6ZK>2gW%=fe@za%tiQPQd_cb2|Mxj=9OY3SgE;~KLS_q{p&{U`|f(;@f^xt~6KgSf@r{o0Q>y(a|ZpR+CIkUhkhZ^A!V7Fn& zo_`;g@EQ+OewCP>qIvBN6;f(5LtP*g$CHx;G^ux%5s-7D<1 z-Im1O-KvE~wD)%7qbZ;k>VXJ$HS7z~n}sw^u7jKw8fwX%sL03W=9-`0@xDpY^ps!e z{1{)aE(Yqgkc?@V9p&Fe&B&v83?X**iF!}46R*an5aEvn zMR&x7rX{qF)!*mhK!x+so$c%IpB%DD$oZ>>i`HU{*1u@d+YpjeQvCA@n=_WFUI_% zr&7&z(%{6gIbMjP>4*X`(A}jby~RUsJnuk)vylg2z2Wos`fh=bmp2_^g6;2*n#xii zKknCXDBV5~P)&(lc=#|AlGBH@qZB{HOWM}79D?(Vg(^oskV7L z@tjDpiN}dCLc2P4{)gWstJ5g>yD?Ifae{a0B*AV?$pYnOudy<$(amDAnph0 z+}a4Ia@ZTW6^C)-G?iT$ONEpDFDc<`6V$EmY3^;IPqMBL*>Y|l5dB`Ht;V^^!H}K^ z5I3ymKA~lhp+&$xTXvvgkbrt8t3qx)d@-m9MK}@Z@shwGXg6aRA9?o+5qD}^GjgNX zpBuf$J00FK3XDO?1X9pW$!m#8$X3mmZA**zic0B<-mLOAp2L3MkB3@WU!+mesBv|{m7}}{HePvtbD26ojcuUD7ne*FfYwM;hvlUio!V08v<|yPacxcu7iHHx!HZOih=R%Cr30T0Q%%Z( zF30s|HI@Aou1U7moeAfcTTi?+{q0H7U2PqvP7%vN*eK)PvU9ddr?Y<^nOM zim1b8A&VoXeCrpTlpAfkYR{~ZpTl|`eE8%4Wxt)Hw&Q;XTG6X7$bpU@d!3{vW721$ zo1i^{0o^7-96g25RuSrt1^^*4yz(8H1aI}Uu%?1838=`^s?}VR6GMe&zgp_2w*avE z8El_gz>t|g9~jS=xjvnjnD^%)`{xSC&kcfujjzuhwKB9}vK*?F&4h-onEOy$UCF`CUc&$l0KX153Azt6Ni%hsl=5*+U4 z)KMRu@pOgGV5`O1HwY~^u}*7;TEh9Ut+X5jkb8pvgD{$XZjm_%z`onQ9w zs$=Fv9A!MPx9!geNUE&gH$L($B_GAI~BDHT%%c89}R-k7B*`~y~r1lGjo z1-m747R|kVQ1-}?F?}$b!tUhj(OX{63h3a^;nK*sw^Y5zW;<tg%|wQXVKj-eHZ~ z?EE3E=Gvp~zIzAz?ZS08_uiRD8u!hFwml#LXm(Sunlp-8k}DKArL}qC7rU?@sS)x_ z?Wz0cIo(Ok!l|dyP11-V{F<@x45=+=;f2ES8?!10X5WH&okyC(UbsL z$$-AJwd|_kekqA}!%&UnBf&4brj*zjAs25Cd+K8kL39SgZ6!MKPrZ_J28CgmX|kMq zhF<-9_ex1h)p2$U^^F&~57;Hk^*R0%#M89+L3O&9%B)qxY-2sD8^aIY^>R+Lwj=p1 zAH!vKwK?r(sxRH(;{P#CGT~)+Q|MYB%j;8po$Cr{Jf?gBG)yU2c~-|` zbUo$kSdxYvB`Y*!YvnY`JY6{um8ptoz5QXVVK~dRS2fY?XYP)^CYJJ6+O$M6riItZ zH`HdVuS9daP{O31Z!00a#vXh{*OP#tKRz*{ly#OFAIoQkdgM!}#+^PQG%@wv7REO0 zNT^NDBHr?F&&j71rWpa`g|s+LMo!q3MZeAE?fiIXyRio!BWtdajdQP-vp1)C<$N~j z>&>V3cEe;NnKG)Tk%{cO`s!Z-+^rtb=0mY zm(Qo~ycmS|oMm?$m5@swOfXC;%S01R#Mcr&g&j?Yb^l-Ny=PQYYZo=@Id-KSMMb*U z5Tz)+qgbc`0R;g8ktQW{2uUb5;3(3Ybd@emYJ?CF5fDNT5FsS=5+MmS0Ydqn;QNmI z{kUa}@80|8j{DD&WbbG1r>r&CoO5|@10>==AaVkdfk@HE2MKuI5{h_9?_Fdb9&kQv z)U$JUSiPCb=&fXqJE@01aUQaFoLXJ$39?tRPB;DX3eF7j3(oKs_vXZDuNr6*asgrF z!v$ZckyFY&=gt?(M=Z`wziw+dSK2_?MDs@Ex?$uEr769mmej{&&V zvfD{pl4=Ja?%XgRXu%DBx#TGK`5!?~4|dtHI|m3=TyjpTdQNciU7Zdv5_ z)IJS0dMPhcsBeGzpmL$byGvz4J{xW!_KCs#dI1vEm@ck9G(LMaY*iXw%OCOL=@frc zSB22y5Kz%E+ZL^pd>Ygc7tVhcO>h0Ox!muUXaD5l4(ZEtG$aqaBM#!mr=2U%f>WV( z=Uo5J*}hc7^;%z-_f|#T%!`qusoc{^mJZgOs%P~M&X=yFRMh_(+J<*kbXexa4X8I0 z!8=kLh^Zd9h_ZZ>@@SAU8n9y0zzJ_}Lw#(}Wnq*qnR-Js-%bB;byZbuR8UsuHG#lO z$RTHRczFu^#G_eh5$UqHr>c#3I5OCmx7)tJ0#fTFAryEIz?1)2v2~|r2z@I$evA$` z*g_4=Td0^6A?#z2pLk&z6t48JsvP@-f(&JN!^YBDFZFn#$u9FpTXlwv#kOJss`HK# z#iUZt+`-M;IrC^RL+HmQY&J3C=q(fV-Z*G-TVa*=6qL)j@Jt4uB0<=D*XLJbeVCM% z>TV@7TbX&wZD@|kwGGcwBPTO;+5=8@JDDbe)$OZN!;w)$Gav<>l?-OTi(uZd+yuTD zE~*bTx$!+FQdT(FbY@eos}JVpiTcv4zlu>QJ{2W{YJ&x;Zz#6a>u`^9gIc6uS`GUH zs71?L!m`KU)ycGN3B^E>Y)*5_Bg5i_=$?XwuQsOX4D{(lvmMXt)dH*EM*@*ZMJ$;L z>nf8>yalmJK7u`GCJ6Qh^vUU>oAetCD$K@*UtdON)V;NlGso{3aC4Gpe@BhW!OM2k z@IK3%z6v9SwnI|81ZPlxQe9W6g9!TBvlpINmP7SG7;>h>|EGToKRc0{Ri2luTO zB-Rb}oUu|GM&YlD^NtU?NPR9Y=y0jHRY9C;L$%IVs7Cj7O9r@KPoc(l8M_!^@(5M? zcj2W~q(13w%Pw=d($ZSh`{}v{97JR;sxYdl7a<}f&}Kuvl@u)~L=0S@)<5veT1j3Y zCv#7a_vgQZKy(X!?+k*98i)CJr|@dilNlm@iiQ#Mfy_IzHhH--*h)X|dq+4e`1K*! zcaf*uid`lyS|&S`3~Suid@y*T14BI`&K_qjVLW`yquJS)+;c4c7RpZ{&$Z~x>tQ1U zw0gX}*UQ(}V5w=^8zrdS*6|? z#C+z-%8Rh>VpSf(x1M(iVv|K+N^JXEImOeGdwWG_4Y3Z;(aLA^-0{fwf{J(;_G-n} zNR_I0!xJ|GaBl>rMxa2E|3q5+?@36d`X%ZHJ}3J?S|KjB zeY@!LTxQ7+_;rt4rvLP_G@^*ObV4 z#nS`J`r$~vKFZEX4#x4{`q#EBO3%!H*$HY)MlP+L0ylwpCge#o`KzREM@3a~MKNzO zboG}U6qC3X0#($gV{%nw|cX2Wr#o3BsO&Y>#^q zUav0foPyt4L2UkYiNg&pysd)sbndnVyC+PPb!F@hLC^8NW>RLf^7Q9;8sjAE+LfJG zq8qRLjx!D)EPhbVTuF0G?v_sX&lGe_{atKwXq%u5(r)0vbTvE6y5DcM$YIgEjTpa7 zOmN}r-}@gA-y>w9)1?jT`X0NAr_q-LS^xSW^F*Jz9D*;^Y`6Ll!X;$ra5?vg(4JXb z5B`6j0vM~5S6-oFLk;)@6E+)Gjc}{F>S#3dUb-}boukcYsG-#N*R-?7p+lzG3!|S3 z0+;V3-dokbyky~;JliT_=j#06(7l^BoekM!vX*3SXdOoOIwpE|rU%`OmFI`Kux?6GAY(0WCu zr)3KcH0Ao3_et%Rwl@ul7_DR``e7R)uI$^FxhF84`vgRBcX$0Ve1}qXYFxBH%uH)I z!yp6F2anvx5xh$DM#yYmk8-RlTU#Fq>0~BiHGj!Cf^Z++t{H|BBbkjGDSVa?q z)R~3-Gbg|cK6RL-bqn6J$zqr}B?195A!=*|T7Vgmf{>B~1@8XUfQxS;9+py66Q7?p zb_TzZx#v>g@eE4OKlMuPcUj7+v8Wkj^mY}Lrz;HfUPgdf;~K*{e$0`CRwMqc$*z_=_9IKW}ywR zi~r*Jce-?U4+;u9HXq#Z99y$%(p=@MdM<+&%MQ0k^Rm81wJ$DnDc-oX z)89YA3HYQ_fU@Yep4B+N&*znQd8-x;z$g5FOvwIUuo(ng1fVwrQhKKmFQIO~Vjzb! zY=5Ud= z`wW2l(LAGaRKv4Dyn79Ont2jjucT8J0ATUlXQrJfm<2I|pWnu!+1T{4h>Zus)LGZ` z+6Qm1NjZ?zFYX87^HCQGj8kGNRB_01)k-KiZmm68_Ak|B{Fu+>gzuG%jHS~hQZsK_B&=o=4-{jg2hG9*Q6Fo=cig;^cM|P ze>Sii*j(tNGV>RP{c1Scetl1=JA&2D_FaFJc<+;x7=g>JE>avfwale0o>4MSv^S?1 zi!!He5_fxJDnE%fPrJcN>t-_3QIf^(MRqE(ggTSd&qQa}F#i-Qr za{s9HyP^N0N|YrtfA)RdwPGN9?NcqCN1vJ6J1VXh3CdfwH5DvGlL{IVKdlA6AMqFO z{p7P7nY#UPB%a>JmCQ(Tx-1uA)i8-GuXPMGKucKMKjS^_$7AI$fry_AdZ!SF84~6p zs8;0xpU>w}KV(Bz$9`aJGsrT)GHfhA-nnb`X^NMTYFzb(mS&2ikOD3(af14y&S?`@ zq@I-1c+@2Yp;3RC6WiG4s%Z{%sB-H!uNE9F3uB-gWtP$;@cA8LBXLGmmq@Wr=MmzC zKw+w~nmJ#YJ)QX^mCJ)&C_#F+3gDpX7n^eCUZahJB}K%8ohb~X6oHeHyS`JMEzuq7 zE9!;V$EBLWdDY^!lNMfc!PU?~M`O}^^|c>C58j6Dy!09F%g@ZQRv_1s;5cXP>78gX z)k5Yx?6N^pn4Lp+{fDPm0u_^B`c9O28g9W`xWm#?eDdT_@N+Ac z&V67v1s-f~P@=>^}NvREP^+iL@ zWNK|dahdmsVz@_N)u#emXFttub$2enxhLzQX2erX&-AMG#Uutt&(%lCO*az_lP|Kk zx&iSe03zxP;S4uqe_-(R)|J4NHH;IF|EU8PBp?5whCU3A(j?^YZh5tC7Xm7e~8RS7p7F*p2KuY5=b-fpt~-pdpl0-p1&l!9a;{ zuIJqrR+oK-Zna4!jn!D?!ZxC*A-8E0T8oFa^%ftu*W>-&Fx22584h?aNOCTVTPzGe zD`C>^2hmE^Coz7CN9iu``9gEX`WI8Lr*ZWOv{9lPBnp_X%pzOMYz+)XmwwI0KE)3H zO5%Z81{PrBE4snx#wNX>!bH_z$RVLHr_GwPvL9um{Iy_tJnEjlFXKy>Tzii#R|}Fd z&p1oel(V7O0$|zKUMW+wSWImL4R?IN5jF}MOzb@P&|FQi$yPX z*RJ`E=g$RmL=o4=$Pv5ku=0C^LehmdI}M4<3dmT{polgKtSj2h%D^ntgIAPkg>v!} z$HzO>G9C46?)K$Q21wSrRvf4C6=0L%f6JPlY4c)}Aab)XVTMIO+g)#)& zu`yzWU#)VJ(pv6nAX@Goyl_)zM3dkh*< z;Zl>Uha;+cw~NQpF<(;u&Fc^;PDae}116@=YPBbI>u=F{u3c(QvF?_#Tf6@_eCugK z&HXd(R4P@ffEhy^!4S%GiVG!uhedH;1 z4rS>ID0J~Hw(}`mQ`CC!n3E>o=yZekb&>CstSqg(WK&U~NR0QvXYq(!`Cd1Xv2;|b z)O9o^DwG&=ubGcRxQ0&bCz<4oNBo**H>tXQv9R&)`EQnt9oggala8o2fF(o7>r0%v_PY!u_pxnTckK1(^q4ZRH#wx(Q?c^Q2q|QYz(_oQTaAi1pmW z>LGhNyE{CI{^`YJWao1P6|tc=7ko~#<4LT!H%+zzxP;Ja*X>nyzfwo(I6w~^Y}MUN@%sH7Yg02+9DysY};FzJtD%YzgwMCNGUPnqq4D&D;q9+>#7$=pjYPk~vJ=CEfj~2MxA`2@k~t~SRz17ns}PaeHu9Znzq!xnYA^<^ zSLl5i5iY@88%QD#v~LhFNy|FFWmX4G4KsJfhYl})&kQuc9pBuZpB2Iw9Q`IxppKp` z9aV+LAdXj8^V3wnxZ&l5b$NewxKLLSN6BFCwoiGpjU%B1v2V5qqxEOY>J-~{tft&6 zbg6uAEWTjkF!nIa-_QceK|*6gbMoNJRt>}sY~{AQ+&maDuHf{P}G`b#9`mgP+X(5Otfmg-CVb90>v3x1AV64yi{D2^3WjaMq zAClU-2%M>H}+TQUq|6K%U+qeGQ z2U`r6v1@yhlj1i*2`^%hMs5d;mEzi4(%wZFV1JE8zay&tL(5@R$n5m;g8oW|9*;f#9Eo8`zRjME^y<9oIfi^Gn=+_|_N* zvd!Xnpxf7_#OD)?3li`E7}p3rtU0Z}A%>uR=PFnr#(|m=O7BxNiRByBumHp_OS!!W z^d;#Fx23LAtG@i|)#&ywl}|PvLKjXe3)=#miDZdoBNOqSxS}k#xHioJkD5tPRhg%t zSnz*w<#$t`(JKprS~faK-ddqFs%~eB*5DT3^yy@=^iA6DpG#Rl#5A=16vUGIp6_^O z32zh8LNV?syACToyViQiEwcAGd z2d*u%%tswCn1-lqh2@)dcfCmj#kjoVSw>Q~lm+{g-R12&+%K14cYSO$bVzKN@PACY zx{&Sxd}-Qn_!ZS`#+OLl@#aIpHQVru{nhqfeugtN!5_8H-fzPcYsWr~Ba2o^%nPs` zr3S?tr&pCI)9XGgC)L#kK6Wy1*Wp899k+LbZ;*wFCCPeUQlwm>Q`u4lTz>@V3-|N6+LpJ6X`rd`&@ zt<7eY!(bvXql-|rzItcsi^4_DPQ>rZ!70ese5zl?uHPtMre7t80NnWBuqP`iLR*u< zsx(ZV(J{$?)@ebhR&hb~zWwIQ-VzuZ4oW@$9#JL+2g4*2;-po$taKF;$7Yi~`cC$N`?;ubeMOW{U*e16fq&gD}FnsqM@iUT<>n)^v7M;CxcCC zO5zwpyF0xh@+3{(8-HB2g1H0T1>F4c7j<9c_qO!AN=^vOdNT5E>Hldu+X*k=3+mTM8GO);T%A~UZ%IdDC+(#rv+$G&>aCqQ3y7+ zO0|hl=k!G=EeXo(yvl~HMoZi22AJwOi(PUQDeuwreL@Qs&nyIJfa50*{PEOpP zP$O^8HMw)LF74#z{@+7#%mWXOv-bLzfaAy@b@j{kXLD>Vbc zme~@>3acldY2xk9&84}rFI*vh?JfWw6mEKz<>g3wpcf=RY(zkwvjtD(M$OW&`%EB9 zLMuA3h4KY+?)Qtjf9;bJ>qNWYvQ4>%7;nkcp z?#BuI)6{?D#g!9)+ErORZt}L&hvNO8IPb~masLsLN~>OlwfFjDuj#+7$dW3WS1v!V zEJC_t?vAo^u+uu!k~KVYJ$e8XuWSIStJ&!ik_3tQZ6a1w1zdMy6LIVLdS_mGEoTa4 z0$Hgc&)MX-uz@KJk(ZezO=GrPPi_AQUXlm|6J2!PC-#fxlC(BE{}U~GH`|YUm*cgP z{m$8%6B$P>26qgTmbdTn@bSmm5a}VNgUu0@+uu3K-7hK1S3&skV^pSw83MukVz$iR z8gofG&|@G42l&o=##{@*dBVz z=2|EHQE|syH>I(BJ|yM|#=O+t*UsXl%Vm1GL+EOeQ;zEeWagJ?st~v@YEVo=;0pbC zYRUY!1+IdFsSFR@P+Gl|_{oz5$rF9)$JNbq2jvnXL2W#0sdzEaK`^NB@JjVya^=>B zyf51;3Fa+ZcYS~d!nw74g88H9nyeK%ho7t3UeaffJ>Js}Td% zm=(WH&ND%o6OYa+#eTAGDwNUcba!pv@-mV3kbie+)^s$L{>sxU=<<_IY@zVy#lfAi zdcEALsKM)U)0QfWb3WVGb2H2SPU!PJB5@sv+`v{TO$(G@PiM45ivc?OD+^w(tu2c3 zb>P{6*6d?@Wo7cS`gU%Y$gw`U;~s53cY$6ROSn=NM5=g0IX$Z0CDeyQxqGS6gKTiK zlj6sImvcXU?TND1(TXyEZ&&QyuHsYlvdHZpp!7d7DD12LC9&Jl{1pE%jTPEN&kTn7 zNdBseH4;0Oy{gXf>aO`uFVbj`cu1o#{86XQ2e-4jU6RLIHm#KPHaXR0MK;A;=Gu>u z^`A*WlGomN5YM}Pz-R&bxs5U#Du?ccmGQMg_?$xD{O2dfM3+nP1^8DLXi5xn<=^V4 z0;mLrfnCa|o0D67Ji{78@klLA$f@-3$o6@6<_wLydaBkOJLc99ADvM{5pSCm*i@squLJ+HJp1XQeb#mz1K$clda} zsrBBKYp{o_$$QidIq+AKlGwW;f(MM#evi6D)0nWOe@Hws)1s_{m*+ zf44Nf4H&JSYNF%ajs!{O3_%s0_RZ!jdtUwFNV~+^L?}k+83a*Rv=>UwfK|zI=exyx zc3AtS=3oZhr6F!R3L@m$FyvDw`2|1gU-W2gv)fq+){u-0SoKd0Epr+=`s%Tj7EJP7 zzJAYXg%h77PW3?)d^fYBG;ejjR=IWuC@XUSrNVF5-qNdLOu)&4l1fl=MjA9qp2Xz7 zFis*O>v8@Px+aiXCDG2d-+{;{--?`OA=iTU){*7yT8#CS`)J+v_uToEIZ46CU#@S{ zv!MMzh{aR5b#ldk99L4Imk35B`-}5b)Yh6i*2eR^D>b7^sGp)nZqJM&XOxd|v>X9% z<(vmd8_~6w;zD3cy)~d4gYBU}-1DV7SM3F$s?dw>r5jW`1q9<-Y2ud^D;?u&Ci`&b zCXXUA;BLkyPVaU8@sQOI$tc-cwCXUzLbE_fHY+me z^Xw7wX7BKeqSW4cOiV2XnUB)5UV72^CjJEWLfaU3nYFZiLDr`zgP&7b7Zk-*{|y^! zsqbKGVJbL6l#%8{`caFP9h<2TA6Ua&bzlW}nPzy+ZisXcjboq1a?925dzap~R62QC zkwAg=@=xXkdg_TGROgk|w&luHbS9{p*PCi4HHff8Hz{vsD2K%r1EwM#yIZ9OiiOp7 zD4iYuAg`eg9?0`-3%Nvvi7*TPJs+$;Aii5q z73BqFLA(But0mctPiSE$R6AM+znflnaD)J{Le*^p`tG^bVh%E5Lh-s3l**}E#Avai z)0zVgisS&*bE`g8du#1ro=MeJQB-#|i<%5otS|Vh$Ks)4^_j(T`%&Urf-kRS=6GKL zbMg#{| zquwuKR;pofWZ^b`J6)y~y96yz>=xqYp2WsCibwr%gGc=+<|OyNanwvnkmaf09e$mR z&4|y~UBRDD19lm~0yvBkfDj&iQwSbP$NMJu);3KXKH^mcHR}|sFcu}EnwrBbcLTN? zf*rzgKn)9VJjV2znL`p7cE$H5ah_{+E40@iRvyKxs&7~^U`Bb?Vo+@QlhAsS2BKW0 zWG{dkIVohQ#W47ONGLT9^UEdOc*rc{I>bEeu%^8eLIZTgPcqG$R6F6PJ*+Q6ExhQ(x6kpWpMl7%&RQkIKY-<0#^>0I4nBrgX@=ETUtZBY_m z+RwT0#1e8PkPJ-V_W*|gjh5Vd_D}5e1x;|(Zo_^LfFXry%v*{1{>pctj6Rk185P{0 zf!*rA|H~_DvE1q4TVr_bb@BbLvaG@*zh85rmtzw2vlewYV5W9nI!TUq{XY9D22@_L z-Pz%@2zy6nkP*)U~5%!u&6P8sccWRg()TB-C{q*WW`VCr9t- zMTz4aNKIJL>Dcmyma4tJMFWwQqa|(G1Dj0&A}sTdoYz<4?sh4ZN zHt3_|we`&0#CO-{ec%*SH!_@as-VhaDLR8r)JklPYOoBidfZ!HhO!QHH$UdyiBbqA zd?iSo>Fds}QxR{z4P)8~7>rPgi%~wcy=CPn)~ft~29N`dwEb@YZc9EjY-hJ_BxQB8 zBH{Y$W@{Jiit)TE{fB~)D!{e2@ULovLzHg2&{aTG6Aw0rP`Y_#miotJF6xeJr)C_; zWq1!bak91ScmGeMBU~GJvDwp|2Qyr6S4{ZUZ>z}BElKI|`{M~>ZEcKpFy{t~bKT*T zIbbCaclAKj_wIDm*70MG%Pe5UAqRx)bnX7vRmArCxv~Ci&Ufx1*gWh%l^)ku1V&@W zM!qh&8nzgv#HKpU)ooA9;=VH5-IoP83(^OZU#DgVNRH$JyPYCL$g|f~35wY0YN!fC zRI*h2(v|1>y5^!GF&Ke3W-Bhluptd|{K%W*`Zgc(b#9pK|AnQ~^KK}JDBltu%=kGq z_Ux2irJ~Q*T?YdZ7&3PuvwEsNMO6qo(clc_Ci~NRX-<{FzzC${SfqnM*i)MVlazm} zUu+1r+_w5rply(B!hkc(>#OaOlfBH?FZU#uTcBB5Xu29iCOiMaW>E2TH&)JiW*;h`AuTDelmr)bet%AiiiU+ozUnBMJ=Ya|fF0km957?UJ1o;Z;p);v&Jx zT+^{j=}VP4Mm-+>r2t zMc=B+sh;+F^~dJMM+x{+lSGr27q8!ka%`=5)pBl!i?l0jsPk?pa#=&(+28PdFi-4C zRn=Zd4Yx-4*d6S=N%GU93YB@GpJ{ayNM%k6nclly$@=Ab3)9-v%<3QYh?0#fB3gWd zUNB3|;0)2xrXQ7DxY~s}V#EG6Dc$%ueM0bg_h4UN&=$>DB|49h7spMKsyArEk4!JU z+RbvFX|7$D(a*^iMni$47VVxn+`kx}GJV=z@v}vFHmw+neGi|gBeVp&d1wp@72hqE zKj{@IB8q!gYF)|%-e5QD!KP(O7*Ul#KwhN`92iioQ3hK6KBQAT_jDI_u2S50IQNZz z{{#7;r@6Z{%w<(IXyMEiVafqHk!%!=yJ5od=1kHwlh?reYIzm=l@kD3(Bl2%V6x){HGv=uHZiI>s zBEe_l-Sx^lPEOl}tk!MI>Nk}&P=Ug-%$X23nn!Z!QyyrQf(KjZV0&-+NWg@8)s}`& zVNMomcW=5~#NJMFst>rDz}#`HTx$X9;A^Gp;v8LQ=)!Czt)9T!7Kc>PPIfre*Ih9R z@_{LIZ*-6u_030d1jHai<`J?xbtlmVQi}k|$KmqYf7Baw(yQsH{@j|KqiJLVzT;%k zz)0!MY&5Qfur2#AZ*te#;7Oi+s}c_+t*7<-P1V6!Q(qwA(_uo+=mNF9k|?KsewO)i zG#1V{g{4JbJ)bJa!vp5H#d_}0&y=o*~$Au@V#;#w>Liw2-V{$=|@ge zrB>zA?UKI=tJVh($1vjO+t2cA$W zZszdDt6T#?+Hsalp+=Qx$pYY2=s@`_tz%*@k_ot(x|_nDGTk|Sk?6f>pv=|VNA z>-ayY9~zCYgTG%J1=7ziEf#sG%OPLj8*o&_N}6IKvTD0}WKz3bhN8y6&|qM%-B1Gt ztgkMrCTa_)KGGBo_PH3AbGXbQR_R0UbKKSqmtl4Rt!MW&chdK`icJ=Wojl;@6Urk= z#6TY){s4~PKlyBk@2Dz##1*1ggPM93bS6RJBdqDU6RGrq?EI1GEGb+0&cT$9Tc|_r zE)$9c7cQn6qD-d>6uH!8i~s4!pQO&URr@^@)Q?E%P1YT#Tnon^NR`;{&<}IZp3QM= z!v#sR3q+V}o-%lM4_aEv@%MC8eobxQqj;#>`!I_Br?;X&zzwNG+X7{gYFGK2N8X(ms-*u* zH*h~iGc|-bJ{4G_3|=Aphpk(8g9vn~GsK(#aku14?QI-nMW#!>=Q-Wu`p*YFXon4n zq4V~o1cPO!9b{C9xE*5F7Mb?wmNofKb@>K(NqZMOld-PgoHlI zTwHNYo$?-zR}1nqn&vk!%H`q1)X(lEBBLM?F}?`&B(xrMiy^vyN*&(o+y!7=5&pi^<%xPZ0n7OGRX^<4TS=T`AV)^M0&?W& z9#+ylax&B7Pa}vA4gY6tgBl=4R2-oY%lTu_a>A;6@50`~+14x=?pLDi?isgY=Z6yB zx>OT;h>3MZNHD(eq0_BI-+NPL4-}puR9Zkvy1O3E+Bp z;POwcTo`(o#On(B%LxAou!9_&&07wI*)1DB{G^;vp!3YkHY~ zjPv*tw9~D|6J#J-!RIA`C7(BNeJr=q9{dNjmrEqRk!Y=4NLv>UWF#zz&3k7_sZ{Ya z1p9+5Wq#$4389g@KYt3@@-JcbdkS)6=O;r`n$ zKjcYo;8$IEeCnGoI6W8ysmlXud^cc}<;thi!3)T^PI%_;@xb9Jp?~+Q?+cAxYk&Bu z#HMfmQsrk(v$UmFMS67m%U`d=qFh5vz0SJE-E!ZM`H)BB+*zs3jCj`$NP`}5-=Vi* zz=l!}`(6T1fbvMJ+fU-8tb$$C0cQgATks0Mjd&>7r50np=!mxe9yxf9V54yC8E@{Z z#p13h^7s7st)u-qTvEFW9h`Rr$aBG;qwF2zQ%um)E$XLV`{dk`%$kugIUe*U3WO1? zcXH#CxbJdHTTNOfe6sW|!JP%N!U5|@ddw+JL9I(U8bb%v@-7EH0gY&1MFGZ_$FIj* zKu*X#?bKv}41|gmi`FFXrY-buML(MfHn3WEe;2YB=kEq~f}VI2#V*A%R|^OK*34`( zJ0v|StiIJEi@gRarG%Ud#qrQ7fR}nb+jGF{RRM*wo!MG(i$OVUD(BL65opmv{-V-R z&VGoSy}uy-DFIKyv!-jnJ2y`){Fsc5vzP7K+daURf;V^8TK-<&8U&|h_o>A=n^iZ1r#n_WhlHikHRy-;%yWTD-AZ{zx5c6KQlVu_7Ki6c zouo+P!5638w7SK@2CvoFnp?hy>A)Ks_Vq%Cq)>0r>e&m9EEr*-(>kfM{+pc@DK$K0 z&86_w>ffx|_F~M}W?{>f`^Fr=*Jx_JvM9-5+o4GSUU5VC5`@hAq3`dHlE=#1@PDVz z#4LE9R{4-3glT=T< z&Cmc%i@L=Q_fk&+3pM1Z;%xa{!VjX55nXzIrOiIvy8k*eiWtV)=)P&r`h~6D)MRex z-|5U}aTr&vcaWiJu+ zgI^0AulMe<$8wN~E`7kw^s&NM5y_N?qM_n<_U20wm@n?SSm%kygoqT&)W6ytfP0ii zP_UKq&lcvfaJ&eH82ju@Uisu9u_kshu6#20$MZwA5fC%ZRQ>t6Q5T~xDMcb0n`0@j zEla%j+ob6`_Wd@*&f2yLQvcJvalujLgTFbWIgi^`Z&pVBDAjL6W z^%5)o{+MN%5N4d^V7Fu>t4Op{Pz9NW5~3zjtRyR2D2J0DwFulj`(ipUhJbp1xd83lYuje(t>BURY zR`06MdAKEnxtgPCKGLjLy6Cy7aJyEnNsvLyiYWAcC~V2J3CqgQN^PlV{#88A`ba>X zT6r`no|{qSwE5Jz!trrm4%j+%hQ$J%Ay+T1Qa=+w`R{66h`%X7GXSruG)io*Dbqd= z6gW2gi@4FG%PVAWowUe_GA_QZaw1xFZA8YrPctSJM4blS?TsTkk!s zSoinb2c?$HtxND~tr@3l3iY`V$`QS%JJ`r_m?*eV3FB~#z?q2fP|AOA^EWivBH{1> ze&1xP=KAK3h6o(t9CBA4p%EMfpS-Vr?rdt6Wril8dAiF&gLfY2V$HO~DF@S`rWhoRKSL zlTO0+_Luilq=fgss(oj8v=Rgn*(J2~*BvZN0?LqmV5)s`&12l}P!=ItQ=fN`DmtVV<^UX?VC zPRB7$b_{dy&mc{4!w=KxwzTt6Yk_C2{Lj;8$iB(1;B!pJdp-?I^lgC(TL<@7A3Bbi zJ6y;D?ZwQUtM-fPk&$6`>(pE8sy9Y6J&7i@oikH5vi9ojBVm>AII{hg@67nB3OT*7 zlQh+vxp5Bu;=0&;k?l>WwTbV}W)BUrPE;C&$!s%WR}HvV6{MVJ6wUlEL0~+-7GcvB z6Tzqo2Dv{vs9d}$1UBw@pNuGN@clgB?JK4*x`}MZwA8IZ0NMa!1Px;+ae(cT z{-IR%-Kh%Wgs=;}A^R=sUrb-Q17u3~R!ZHPXZJi80Lwp<`!}+6i}Bkl3P6ST2NEYI zUb9Vw`s7rlEIp5Y7)hE9&Az|nNZP9`u2|7%7eqtnA0~uV7<{50rI?(hy8>{q@;lcC zvKNsTZ$tM|R1$Z3&7}&66hZPwiLjz_7gLm7N9_}1U;vCuk`|R@a$EYuy2}@rs{#fX zm(jAR1kD?6-Z>`C8?V_ECjlzyj=kX{J#Ky^IK*Hni8|YahnM z3+|^Go6N64LM_w=dWvqQZ88P^eo)%v#td|Sg-Qs1yxy9{PWtZMz((+T#MX{tX|j%* z7%~z}HY1bkIXCQOHu8C?-Ei#bBwsdAD4MaKJv$cfn78yeF?RxsC%|N8nX}gK{+)4_ zoMd?zL&eke&sJ8@!TT=3l_g#(=6~lcaJ&n(vqS@JSa2jMlvSGm^Si69wZqo(&kU5Y zM8tkGUY3&JIqMC}rX8;81Q21l!7^{RNzqNNv;}3^nZ`HNj~RDL+p@JUfy_DoGn50I+*hrZ(?3 zy1oM_S&JG;efDe`HRB2Bt`dfQ*KsnOaL&wu8d5b!i>w^i>|MuOjW&uM2U!awWuragCpret_He}O0)4svZAEj?tYj$}M+KU%>3Hay5Tu|RQT zG1V=1?V!6rThp`?&+#O2!9H6NuUxnzLJRNZf%p6d8iYutl=0uQ(&`p%z4P8bTM7+&P$ltcsx+Lh&la0c)9vWCC?O>&N@mYO zUrjB4U3s@lOdQ4neN-U1*RUO?j1HK~=lq2bcjrmx!05u&VRvF`WW!`Kp{*b~1c= zE~9@YeV>KWFwOhC)r#|=JfRd;Vd8e zeyTJr-s=q%&`_SA0t;U98a$S=b`<|t-^;vtKkHleYYF|ljI{`);lBWlP5++K@k=D9 zEDj9>SbJU0wbSmVwgYvPe%b@)Xk1(nO%fNj$}dYcw6?$~E$JUK34Sm@_ID|eRqxd< z=a`Ve+h+PuEQByAmXU5e)9L$AIrdc|C6vuTRdHU@p|_eQ!98!%z^EUeQ7s#E7~DCY z8*=+g$8fjLkKb4e8DHwXfZrh3<#JM<(yC!Ze2m zgN8~j?suoE#jpS8;rz5xDqB!ngsd8D(zZb7_Ra>k>-TzQ8CfZ? z)He{lfEyAfD!UPDcF*x!To`}c`jUjVZr)5{+CQr<5)cR8Esc^&7%`PmPTawSvRVB01=LS)9CN^quWT#5iTz0k?BG zEmy|apHD|USCJK80sg(XxZ(J?_UggMn^_hHYJ1XCl144Z9Y0e|4~~0d^wf#pSB4!{ zCytsS&ODeL0-99aCCartIkA7NO)Ff@9gGP(-e%KtiH4-3ive=%Pm5Qju&PpCpWQ(&7XHGGbiNN)c$dcyd!-|@4$bhW9V!w=|Q&7=fxwj;D(*JZ_7eISRbEKW@E@89Yr zT4xV#7S_?8bulEb?BCuYb)O{?`CnCvRb5sI&IIRy74~4>>1Yagc`HQ?Z*wOB+m!uC ze%&ZLLjyWkH<^WwA`(&6S@LHz0)F^|^CupL_%F|l9~X`nIb9{okz4X8U)R40dHj|; zmp$3EV(vAPc-#zp!!$ga6vy&^>-@=WFH$VvI;VG)&)X_aQ$PT2r*FcTfLwY(2#Jp5 z%&&!}gd3dctNjkX6~Oz4VEX@o9N~r!lJWJo>giECxlE~j`@UXgrLobA2@PxeFMpVy zL=Eq@2Lj>!V=h+Yqjki&cTL!u`SySQXvl8Rc~;+~u~)*Z$n*8N4=lCQ`WIkzB%f1v z{o?*tblV4)lkj%5FQNhriW!Tc>7g~qiQIYpFGxezfd*LF+Zqg&`woEJ#~dC*wMP9# zicNIQi*x%6OYLT-R0B-X0`kVj#kfcfaEQquD6J9hz;NBS{?ECh)onn0? z)w5IB@(w6l0y+)Sm)6Y^$b)XdqJVQ%dA=#vX)BRGg`3kZ$V2O7oKt3d_{3WP?vO?7 zf+o{tI>R4|a&WW-3^8?+;bKBs6|6?Jiot@n{|9sL8P!DB_l;sjL_kGEML=u_NN>^= zMUbi>AfYN!Ly=xW5dl%Uh2Er#5PAqCgeV9|?*s@*KuUl>f|P`oa0ajYxt{x+FXz*{ z*6VUDT>~?-XV?G!?_ZHp-n~ox<_d29cA#%tEkl;W(DJICzvZJE@2fm-~T z$sHw5Ld$<0SncUrRI)*;U6q$#P2&so{Us~oOVDH)eSioKFu5<7eJYO9^c?&GaQdf) z4s6_k+Jb0RtT>}LL=~v})WaKzv0SBA67a%^jW&GdsZ-@089y_Qm%W@cwDskCD!wX3O9jcJ@n<;q8`F@~3Yh7~f#3JGKGE=ZLV0o`A zTvUMw_L$CIF67+##}t*hO(#O_%EUO3=e?G1PLi(Y2R0-iTpl1A1@ zM;7;7b5%HiBnbcrGIA?0v#8$SH`1a2G`E(x_G;4*vBKX)=KzhSjg=B>FU$w~l`LgZ z*N&Yw+i@ZEr%yG2p>W^mOT+N?;poYR{jrE<-x*Y+klKgeZAIt&IA$x!$39Lb;uVuR z@wR5-E}bn7lmdHW?mFiRJIX-OIqxQ9hSZQ~0SQP_XH>7RB`F8j3YCWRI3Yc*8|dJ@ zslt?&(}PYUbM?QW>pS^^Yk7g^BQg3$@m*N^hUmgzAslZ~*qqwU(Cq{_?dbuq_`)_t zY0~o3CeHbp&V&;x#q&w~sY@R_BDu^&o7OURFmpZ9S@Y@VbeKJt-%8i)fenMq5|ZPT+O3mHWwsf9jmQrq-KlXC}>i5|;&d?q6Y9khE zs6p|QB+o}(9!A=I__P%#v3D+I9W6GH?cF!yYGudXsqZ9Syu5S0o;vk*3Z{ENGq>4Ft6HPJ)%1hq}tlM1^ZJNZPz0eZ>m z-BB98BL}XIFq02vm~EzmSHof!*Aqk1!e$2NKU8Oqv|pqg1179Z$w+VU*=@Lqs7pu7 z8~N|cOI^}VBiX552^~oDwaWUN>qaq#I|S8h?!Nq~=JmZU${&j7Fos~*+)Hf$cw(1t9Oi3{^N1oo=eJpva9obiichgxJR~c%qwQzs5zLKn~2%FQs9|+i& zndl_+_z9)DkzRF0Y*ddk4|Z)C(Bt;4gRFPFLLX@pUP2*uJ?8xA$h)OGW2eY_wG8m! z*Q0aQH#q2&M0rZQOeby6Gc{2ua3Fupb}eNu5$||8z|Rxpf3;n~T7K&0X0TR@uW@vh zd8KTj6`*T})ZC^$GRV^G^aS8?{;!^B8>4UHLLcX{Gi`mg4A!Fja^IUYctmvQ{j=4O zlTy*}Y4K5@7TSoKvFl8*shHzeJRDP-s4B`)`uybkH-OxyyDqevK{e2sHX8x6la31w z6d|yN^-2y|3AfWFT?X&Z5*x34zJtDyw7E|)_{F*+ZsAWfz2pDGu_-07{7@ien3eC+ z7cyc9(|#miU`y7?B&VyTIa+r|wtJ`ENR{=-D;b8q4u0WFLy-Z3YcInJJuk`Yb*t`* z8*uul*M((&d+(O#k^0bkHfsYPWJt^=3n-iIiS-TfQ~m;$fGkA?nr9F@;##rYu%3Fm zweJXQvRfm$a&qqy_K#iw=h05&z)m2yoyl3*wfDhYxbh#2Qf?2%A0;z*vRcsX<>FJ( zUys~8F8k}!>rHi?i46@9LnCQz(LiT>oO_c#uilgG_dz|yR6OK5=-3uO;{K@LANX?m zePfBg?BXRLkGi#=7`kk+Dk-}fE>i8cr9BFJ8$x?u7H^<6J*On?x{ex&5xa(`o*M1I z%Xj-;9RDmot!*aCTbp#xS?B1NP>Uy8=q$x~O=m!NWD+Y0klTE90Qz|0(-;(xYZILQ zb{|plXg`hrqcwqke7kvnqkXQ+4H~eu^<;Z+-TkxpvfHneB~!CcZkwF&`+=+P=OHD_ zcG_k`K470#hXe1tb#Syv0Ax`_Yofv?u> z+QHYAJPA&Hc2mBLxvYOo=%F8=_Nf{?1oN_ZHnb?<{hBQ72crOMwVj%X@3z|i zS*J1(kf5Dw0qb0q@eq-x1W%m2a&qxWoVWLrtIr5tQ5%)>_>+tK%fHInU;cqzHt#ag zX-G=FxQ&k(H&PhApvhc5hA{%__|uo9WGYnI36j=;%)XOMvv1lDB~2| z7qG46#D%_n>0%-tvMr!e6RVcun3PNJ_i+j9h;*vxdVq3sUXOAx?UorO$Z3EyiwdE^ z)48s_Bxs@=h3AJx{vQa?#h+Wn__Z?abP4hfCdBNt_@1^@s2!p8gdOb6w$1@_9XH_r zq~8=IA!@x<{xN9Vbdp=edVkO07dM*3Gt1hyAHCORiZg|bK(yTD@Le7_R%ON1&lhb< zpClK^o=~=deKbGb`DIQ?i!OTZ$(a~>{o|uhX>d|jM73;fIC(Jg4!LY7Q(2zre z=fkb69oXFFM~x#zg^+&fk0KhrP*$Qb7U-emhbvn6%h~B5XYtQV5T!x?(y)PwfQ=(% zB|UEN!Y8;CC6GB!EV+D+bGX0Ht(c14OeZqK{#czD5<6BJl5&{Md0=nmjXjWMLsI@U zbYV_?o|nyagJ*aeT1k_>3ede2NEJQwd{+|eo6HfoYvadW0&~33Mt+SdY8JkkzNfM8Zx@)#WYpQwtywvK;qR*qYvirmzxdzQU-NDdZ zro~)y1eO+%YF%rBB+ENc8T@h@a84(4HKIH}#_P?hJMS+O@#WneE_iP_@rYu7~yn3VSW_Ygwk(cKyym-y0&aN^Zaf%nkYguWDEJGt* zdkVts;25Ef&&H1dT*B6RT}CcR`Hj!3*7=;ta!~vxVx(3%C=@ilgOwUMiqCLEdE9hB zTwZb9t=HQQryVDexsc@!drG;oQwV(3HZ!(8?PX=0Ej+O6*38eQm!lX4-!|!E=6e~# zCUg67TWmj0l|jSfn8Q^6ypKA_49)MTBbI-5w-t1Xi+d!D}>HLYCJy|le68< zy&T2(u#nl2F<8{#zNPn)naxAcon~hYcEjBx0Kkr;2mJEu7VcWKpiTbIv#f>gpRLvU z(>H;C_SHfeXZ0pM0vMvLx;4LDhnO!htxo?nr)}PRyV01w5lVH!6cA)w192{Pa+}AQ zEY$ucrRtj!@j5vhIrZK-KndMM{<&D5$awzH4@i+vul`L-fms&$msJ2OqC0A+#y!X5ab+19F>eTZ<9yIf1mrOc8sGoDnhr5XJd8;WFUb-n0Rkhihhaw z%0Fy1=DT1(J|}N^+hL9W>R)h*U}|m!Jh8lM!d!2raO1+DS}j23H~6va8?nJrE9w=z zEW1d5-1dFsz(4wRL@E1X(M>vW60|Oskb|_*Lk#@YlQ2;l3_;%fR5-NC#X0zw?Zhcn zL_3l*@ljrs^hp+F03c6Dw$4VvAbNQpa2UVF0JGpHZdd$zxfuLAWL}Zpj7`4G%@3HJ z)d=$ek44C1uEnMnx9@$%7ACM5rD4Rd=Rn+Ku^uP%755>*A@db@q`*T z0fmDGJqggA#0fwO5rg3~&Px32v@OJUv)vmWZuk$pM5@G2F2ta76cMn@WRmoIn6qTT zp$M?4ex-Gj-?-(;3|7$KrPF`$(XfMmMRXKhEon~U3In+Lr@qOsSO7fr>M39|D{!m%3^YKWpb7*EzYB-aO8nOhzcm;S5Fr zOOLNZvb(vco;|65sdIAByKnlqtoS;5tMyI0#G6EGFAMrK&2Tb8_*VRU6?g%^&*C-E zs6#QzRS{5&Yhl~4@=f-!UUTm#<{;+9i?w&-(>A-)mV0*AotM1B`wY4QZ)_FRBs{}P z_+bmk%!_uH3EX?M*oC^GJ`@M-huhqV$pSF@BFb8HH`S8H1+n;fgWB_x!!to_r-5%0 zAG~}PJDpeVp~S@hsgz?;{>vuFr1-pD$h1e52Y5PLv;wsFEq zIi;}V%VHpQQnPWjZpA=J6?fNPca%067cc)Wjzs)b9f0lxQit}3WM<9UTgN0xPqqEz z?dWcm2RyFbp>9hzmC?5Qo-#OTAwpL23)zeP#^?P1LmES8`DVz;zh>(&R5;;rKqz~v zZGRXs2{vT8+3)nIYai_td78CH)Jbkno&0oeTI;d?xPS`M#o(`0Zup`s`%9-vc%o`$ z(CN3c0OY4ln}Sk1ix%?jfz^oe+N%vqZE|axhn`~IeNN0OGso5(P|@~cWZ%cEG9~Wp?#|M5v=u44mMLTMoNB*R z5DUbhKT;K499 z`c-erXG0@$frxrw@9@oMm(vZDa_!mq*x3E%^AMJ0b`@ss*#MNYI35pYnVMA@qjq@JwmTU^`f`hq+5dpAs9S_yFH zECs;9^R0mLA{f5&YX>??>*>f2UHjJML$sSPgCVU8_Vz8XH_@@{)MH*ho{x)^HhLa) zo0z+g2%U4iIoV-QSfF-u-aluvut^xtUGo&dO_g5XxHM=`=#5UHS@s$;f5q>DEt3+e z(0%_qUSt5iFpOGKif=DZHX2ttL=w_v{l~%+O5uoKf;tz zYAgI+${n`$-h(+oqI@n-UHzJe@7nWf{vLYQ8S0Uf^ z1o!bqusa}hzjv(5n*76qY~E2um6!$_{;zD z5qPB@cp%ga>6t@$E}b9r>a0U>k%Uk0Thz@$$^ryKjMk16h&J^6-pxg_A7Lne%8BWP ze5x4l`gCfsYID%%PfmZjH#E#-Lf95xE(x#w2e%Of;5I_<*MXU@ zxwPGT)v-u2EzNEO9KuviNCNc93p**{h6M9d6&E1Z@qmC&MaOJCCTg}fJNU7?4#2-% zyq1^H5%&chhmjZFyEkGlYQ!Cmf9X=)Wl7Dt{AHet5 zBVQ!>8Y?OWFouiW&jJ*)|9~<3kk$M!Vkn2Gmn?u1GyRo7`UOK^6?Uz|_8zQ(j-!vM6 zr8L`pQ%Tttf_|V&2R8;fVSYrWM@g!-?;ZI`3Ean`tCp_{0n z9+skYkP$prNC)knoi+>+iu(z+?M~QkQ(7$0RZ3Ka+Klse4Qa*{p|hz;B29W~Dm|GG zD{=IuoFmunfv-}K3%o;bbGW#Oo>zgjNTq13bM?Yen@25L6I7c4?!Qf z2cl<`G*(#2j8w=Z1x9_(FT(fehRG-LWsG`9e{PqIwQ5pl@V+!?#%~`s+$r*0&ynF- zd|9N$HjawpukOYDK6_8!XCqba!&=%NVe|o$JfPBDG>Lp-L|#w(^<;xBvyeG%@~w*@}qw_n`{`6RnYT>~~eg#g=uK?R84 zt1c4?kp>wUQsZWguMz!T>0;n~2w+X^hn-zv?vRS7ux)D z-kYl2y_S>$xM}C;E`>b^t!=CT{JdFMnSK9MOe{_VOkS$Ng5^NU(_*g3BfC2DY%k7S zzSZqmF@5g}!!9=142<=3ur(qd?aEi{WI&Kq_lvR21FsNq0B3@0Gx)uSK{vBcCC`4` zM6K8|WQOs2F)V0ESX1Q!#B>sMX%#>~Dk-J8o$%%V_9J&Sg5dRu9$a?BXS1q%OKtQU zulLg!4~{i6I(~AFq}9IHP7k8)w9g*`_*kUbU?E7nkyKzqU{}ak05<9`-r3Ch}Rv8c#Xa#cyPVb zM11Gr&?hQb$fCdiv4~vBF>o4>dlvj1peNik=_0x4=#WFkLIjWP`n8q4MMqtyij#s& zcHf(K4V9==B^T2Y@d}ftfCmNm>GzvJrx`ZXVo`++`PT|GeVq96KG8L!@$ZTo*xDwz z+Wr|3Q-L3>wmt%ufUKGGuWfZwig<{uG-8l6dga?SA$C=Ej{3mU!~BI)(WW1RZ>;EM zid0cY4_GH&lC;x_bX?_c#_^1~L&IC+l`X$PSj z={EwZ7b}ZCjFAEHA4(qaqaAj=im4t1S1bUR!lv$A>hGUnenKagrJ&|(@LxyC3uNXe ztc`%j@$^2QthK6yDC|v6#+EDo>U#=oa3V8QE8fnmD=V-JmLO{%C{h&@8@2!^4iDR>n^;thCdkpYGPwp1r1QXA@}BjT)~1#2Cenx4-B`vFhwWT@<$tub71$@0Ulrwx?h)ZN;Q zX8pPEv2U_3;4J;%`=Jnbev6TSF%p&F#ZVZGo!631|Iq9B#=HLl_wuTT>zB(XXA~ud zRh_>xpKKbnVYYpz$sE1?wStRy{ST(<2kL`>=r7vMv#zJSrSO;TIA+wp8|!^rrlnqt~Z(GKgsbZG$^OmG9LO8Dc+FdyRpkv-gn%=&)r3(C_IdXRq)ba58BB7 zcU^O)cuX{{zilt$+4G(NV4S;{re`~{fkr==Xg(i%xk%Ak?6WVU+}q$w*%7N(8IM*G zZAT_B$$xspy67gceA`#l>m4IZ%)~qVP;RAEBZ_toI{fqY2iw%qAR>R)_x+diK_4Vl z!ip<%_b=+jq_gnYk3NB4MnQElUG;QQch!QrWsfm(V;CG1`h5`EDxvPD58HaB$owe( z`>EK<>F91kWL?tikoi*wD;zVEQS)qsH&OPw zn@+kKxiikV$TJWsx)`wO<~AB#=Q>b4eQa5~il#sO)UW;q4qO=fg85=alJF3e3$I$# zD1zu!tT^dWF(Yi=`lc(hc*_Hdz!*u&+tsyQWR`@o*iU{7*trm7$g9xa!$;xdeAzu> zmvGD~>+H+rM9W6a)<2fd+wkZ+?7~GFlNLFCY=!NyaVYE5_d%4KA_W;vzu^ike8=zC zR9ejuFEl3q^6R)67#ed9llGj4tB6}YcUn;SeQa8${dn$kzr%&iTcj=9gn-*dc$V6N z1fNrovDZ4?4rGZ2THOZW@avAqM0WVOmR(rhDwDtSyFI$WNqt;{Qh#alsYjx{JWNdT z*^f>vT1kl2`ZBkH6}T2stD3EjDJdsU@P2Z$7xIaJ32H@YyZBSLuJ~%v_%FzOEq`3) zBM1}Gw|a7UXh!Y93EzA2p%R#KbACS4p=!lppRJ`fctlECXRwAYroNPIvGos#8h$2R zjXZ(!Ba2wxzDlegp9wzvTqK39@nh?${Q8|l-c#b!f4(#BOi!s!gXL!$OpdmFO?&l> zcPrc8w?`;ml;5^{EOpmRcNXFhwGsVY?F%Qm@2#{mGC0Yky9QAd_eVi7S4N_#sY3LX z=m*M2y^VDtLkr>_`iZ~ZM+l=|x57RXw`L5Q-cWo;=6~63o3{3_EkLuqAR!<&RdUfD zxsdAZN9kyU+tNjU0i1`)x)-JvuSsEv?5}L!Gq73bqCb6+lWS->d%n&$3N(6Xs?8H8 zppt@L@R8)OX|q)L)Rgw6(%h2Qestw*4brcE#(#1gr-V~u+Lm?(dm?ucsjt)oi(q$d z7AQeqm|XBgcw|U|>~BAT+8?vpoQ_SCoGAs!eI{}S9QSS8CdsqYql2Xv2`|K@Ez|YD zXs)4(s|DB@*c;kF+Bh=gz12oEST#p6^!RR(eUBxaz^lpS6`!Gm7d%}jWuR1Jg0!tn z2Pl^h(*PNL2S2|AJH%SX=rc%8^QjfRo^+U7sN?0&(!S*qI>DxaL3=s>>Ex^vPX0V6TcSFH6a3!=w0 zzqd*IdJSbQqTch94Do3Z9V?7iX{*u=z^wR{k3fSyr{jWSZ6lhb?Ri2oL;vWp#?32P zI3}evLX<`chlyUBQMF7Kf`3U;87)3h-dYm&4-HBqaovx3)r?dpwNu9jXKuDXl5-Q! zT4+&Zsz39Wd+o*^u_4uVQGBJ5G}*pl4^BWunx7)V?ind5^cGB^k|h;0B$y^o{6$X6 zGph%h*&+sdJ&<@sOHZPs2Bb1WbP{xmG^ITR4Gi-=Z+|+Iyev zaPsos+fM_X0PvRa`g`r}(St1F_nyDkn9eXZGh$){==*dS>Jordb36T)jP`DoG$Vda zeP`cq+kxr~T(7_Px6oHQ(e#J=JIyNkTKjNXh+_qSj(N@VH}%Q%dt14}dVkZXGjyLt zu=YT~J}&Cuy$631PyYu2%EZL-&x`->y=Z3uf+iWKVV;1E-F~bw_i%IKKmix{ zV^giZQ>i#_T#_g2T9GQT-5r8T?VX7E)UhhLvV5sBMHmay=1L+Zbz;G8H!<9U6%;Rp z(yUG6^xeV2=CeS}f8Y2mkKT?`-CdTpZ16mG=1g(bynDlT278B~qyP%OIT1elbmnMJ zDp<5VF(f#L704>vAl9%1M)IrpchBCYqgUqLm9M8nL~KYqmo{We+(~-r^J;t3g7nl& zMId-hjr;FArq=t^5}q!fK2xPE6FMW%Fj=3d+Gy=1lJeE|PO)x#V9&P_Lk+tmVdr_E zD}fY3kzuHGaB`Hz7aOteB42Rp3Ji}pF6y!}YEuAHEFCU4Ze4$d(C|7^x~-5hUIEi1 zE20bK)iO;qNoQrx$3H1GBT+?WxaF|4RXWW5ueM8{!X5M3&$BN{4(!UFALmm+ ze9e88y@WM&a`+~#T0rat9O2K79IJCRVD6RbB}$P|p6^tzyhCY@^Q~AYXpS%foYQ6f z=G-=|z~T^~1G+hCXg;`Yy}qrL`sS!d`2E17OBv}SV{5gBM_M}BIc|+Kb+WvToJ#H! z%1|kS*_-W}+0_7l6}GK;;H&}RCbcw2n>(d|jibDdI=6nNVw!6P3yJ zz)4mp2h3GFjJTEi0RJyDn`>-tJJvrPe?xyY6WL%C9B#(OvGEmEINne+YI7@lfiA4k zi;CicyAS+m(!n>Cjw~D_tTG%%?8$mI*z%sDb+!HaS>c)T5o=p_Qc|c1Ql-P97sU)$vkdBg zWlR&%woeJrssd@2-K1rDaWvEHD}&>Oo#lkNCgduvk;MIK0S%h{oKDcI**lC%- z6p)c%nRfrd&$Y83yVy7uMG$$x$+$0dcHI(0G5qi2OIoj$NU=%fZb~FNnM^P|vBFmp zH_EWmN?;kg@hHRA!dA%7rME#cLRU z8@nuu#)6+GMQhyp)A0GKXGPwwCiw&HO1_(A@$s9(#r#Z6MTe16QSaW(-MF5@1CWoZ zU1YwtMl}5PrPeRJjtqAgfeqFkb~kb#C8cJoYs65&4A=ERMvOLW`k zYi?4bQVz8#$G1Gg*j21UI6q5`eRHLlzkERxMubknW|@^(*N@1QPeRMXT)uQE1Iikw zmOC&1(;`Lpw5%(x;m0WN7&fo&lVc~`;D>F89`drt>bB>!3)J+mWvwBC)lWX zf3K?ab}H8t>*qTF|8~n>x^zo!)2s_8HibDqh$HXZ=(Ns5Lb{*lx5rHZ>*u&asIF)( znA*iZB&({vM^E2EMU&MSu++*XOj?B7^KK%bm1`9K@2jfS5i0jG)vOv;y6bT{S!Tn; zIF$yFh2w_D8;7BxlLmk0eex6776%e}8p^?`cidh8-KGdCXD?MRc{9G$qA+{_YjbA5 zL3htegF<^y-Ws~_IMWOGnxaepHcv!^xA@dZ1?C=Q#Fhab(B*a>f=x7rBUhu#pB7J; zCw~=vvLz5D*Ev^AsUnlCf^> z*(p7Rs#OWJED8(F-#rOqX?o)d6zsVBoBAp6NFaynz@(1>n5ev)&OGe)_V_R%KP#%& zQ3BkVH2NW46jW6%z53-E!z&G_8$9I~?3AA~G$6^mQ&iJ;HJ05?j^oUw;bfs@U;rA$ z{##M%>WGeTl|b(&Q2Fe}drC)wOT5zbVPaB0#(2P1LuHYo2Bq>6cxAOQ%haITE;S&; zUh1*cYFjCcf)V0PHYI4~#fg56}zfA+LtT154 zC2j)`dApzK;Y}gv->=BIp*ha5N|!YPDO@OG1MB!MH!h;95#RVF44Ykk>r}z==PAe;GpxT&O+0~CM zkv}lefL6?R|9^k&^F6Hur&f+czqXfu%|6PH|J#I8z*+X7%up*No=;_XCU#fOc7S;| z(EAle#aRYdY(A8?E(1L3XO)Ool|7*!J}Nr=Mxn+h$^%E+XhOwNcB5(od*!mE)X-IW zenH!h7hT&26?*wg)`RyQD3f0H;2(KDJD6SAiXN`=Eq&&-6pukuEtH8E_3Z?7J3@yLg z&ZhI)IZbtrxlKD0yVF%m9stv&8Z-Ff+uM~h^$dwym4PEpfz zBT^#tQE&-gp)!QIdTmr|{7|9ck{@8abN%2}JhUdP?krF<(EkR!9V%^}BXggqB zR|2gFw1$t1ONU+be?m=JV~dY{%x4i8DV({Z zRUf#rul5vCCXp;uXOkg2erOW}#f*pXZL-bFOqwb`^hP!ww?=4kCD9y<3A34fitPrQ zZ0&Wzv^om6|S(9?Z6a^Q70-|?8p|%gyNkfV4b5qktyXeXM z-*v$)D$|Kpzc1*s1_s_u19akm*+b6Pj{VG;E*&i~qjQ5bOCYntXe@leW-0c#SJ=Xx zMr&4)(x;f=GDN2^^wr05o+S}yT^%2&@E%j9TE1q6vn+T{ShTFf&=PA#JbhEw6qDh~ zGwi7DvFzKTSl_74HE)6J)jEiKXrPuO?I%Avl^Sc%g<<@9V4FLpry6~=I2h!}jrjN* zZVmY?D)T$@UxWKCtlvwu;;&J%&&N+kZWy-za`B>WCL9O_zpnb<_RLFkLxkjv{OBo_ z!LWYj>Y{bc8Wxj$zzN7Wmiic7|5J61)`KzY--bPh6Mg|Pota%ix%g2%&Osi(aRDWS z0HBIG#P+RJ(h@h5_iA;g zy0;~~!5(?mE*h;_6a%T5VD4_dtF!a0-BDp)+3`Zb4PeB#9gJEcp)o+aFNBmau`^~* zr|>W?0NaAQ>+-a5ho+LD&~^C_=&l){LoBHWCR)Hj!r+nQKh3sw;nH>3s=}HJgIQ!O zxljKcuZ(CXjO@GFI%-pF9w>1tWlZesAl>zH`^D01wbCp-D-mkF0Llbfk||#l42ypN z8Vbj7-wFk4k8q81kS=w!?I86+iHLm!RNWt->TCm6#Tgb^QS3|m7cV>(lN3vICCb{G7Wo=j+Ts^{zf zvhI%Ld6ANK)EVK9sfYIFo}c^dBpJ`KSXgHi7$Yo z@#7a^(eUrE4=M0@FU^X;ay0_5QwJ2wh**hj1Ljy$wHY`eePIEXEiN^K=y^uPb*6q+ znk=!4w2dA3X!SyA4pKY1M=lu843wAWu1mv)jGi1+*o0LW+D_f^lBd;In5^6T(Nata zO;)@YE9S188@$1$3^kh%ix?8c6+h4tH!G@#Txau5eZQ(JALN(W00Bz>t8mlt6SDha z%Ym!bYe}F@JQzJ3pb1=V9A}Icdwz-6!o>l-m?MI0n;lWq3Y#v7NCiJWEKeCIUsH^ zy*>e~sl8R|JDLP@sM2VV0spv&_d_LO_h>Iaa0uI}xdd8|DAMyd^yT)}9u7U+B%c?0 zFZiv&UQXa9jxZL(dtz~j|9=HnA_uhO_W;LYqu)}2BBxU2BVbDf6WWYkQ!aXj~-jPPwnPEe_^C z{3_FLrBEV?bNf&T)t;(p1ecE`%D%1BLYM2WGDqD%bTY#nWie%~+ z)erx9KKGzGw$90H_pYPDK?T`317pBL|5kw#u0N+g;jqA+3%_tvR##7Cke4E-mLr!_ z?;iBFTk2XljO$_r@XI~l;66!Kmv4)4L~WGC*Y-Z~(F3}axytgY^%r|S(6E*gzOFj)%XcWNni^8 zxWG+r6U5b0nC}M`LGO84BMKVV&Gk!0?V$^u=Q)6fGhu)YP>ffefXWzD#n;l&u>ML| z$5gg|p8qMq*XEqft+!*mlV}_~sgK==v^MY~aX!IvB~_-og9ml{@ggwFnraJ9H^m49 z-(ArwJ=ZxK4w3bHBH4eCpxU$r%6(a+z#uiXdLXp<%2%?{pAbbmd2(;G8$j@R0OzU!3y*|gE#jPpOp|GAE?Sw-od4(-Y%ow8F@?Lt@1f#3KLT4hMB4RouwBj4QjF~&GnV+wc95qm82H?& zz=Jzgce~|fCHmbdCxPVldw{wS$QXCH8d@N2^cN9S-2vN#QQ z@Xn71cV?^70G1<9m5`(%MMxeZ@681&ah6y3ehf zhWb1s(9!!9|4f7jgjc4!N0CzU$rZkQ!@1$1WbYc88G%DU_mK$o>LFMSy$O*$ggbGN zng>dKX1R0HKfRn{f4Ly7@>lom*mv*bt=8o+dn+nK818MPa`u0PssF?`|K9kYjq|@z z?Ei@$15+bWb_|pMw38Nld>#L7`L$ti%IvC?Z_XxF*Ojpshy zrG^@MHJ37CVc))5R9sVdv>5j-6>i-^6+8CUr?SvYG^$bbEe-tKE<73L3;vEj2R!5E zv43|*LTrm(N_)3dzfg;WVV8R})dNFTV}~a2M0uD4WO(9fVcV$frEa3Ezjyv6AbQkC z-%wF2Qyo&|cZ};}Po;b5$3Q4|^*gN%bH-KWzu<>2vSqMkIU?y*Q}T9PoVy0j-`$h+dMg8(Oo= z&D|uwhH`#0{jO>~X1u7^#Wq=-QlO*)BtfeG-81SsX~|Ddz^e+)!|juBIF%eDxeVi? z;4op3UNro06KB2rHw*#3=mf_iIjc=OW&;o6tgOw1XJdlKV{Tzq-un3b(M}M|ZqL?r z7)X_M+IyKwJ_MZYzw7}E&VNGm!9-O!y^Qnweans`2PYX{5uL~VCJ|15vbD6tYnwCX zSYOIX3!uhe_zA(vtj{K3yQIvag^%$rR)r0W29!y_fmp(sf19g>ZSlv{^32hdV%bDm z^QKNpW^1_kG0-4)+H19`I=3kGo%6;|%S}w>ikAoCzEP8{jkNl*o|ty>VzT>|O>F1R z`vGan*XF1HeP9OvV9%WmZ9hv@RO`hUtA+CvIS*tQj$`!4cj$8;m<$9fUs~A3wuL!6 z=(Xqyas>5f*^W4yML}-=zY8XGz(Hq{$oluo{~erBrrsWeAY23G#mnvCv3#~94k0eH z5L;c9XN7Df3w?KB*+J9we54q$92vDc#av3giyu*wTOE*zabI;Wxvc&pD*T$EaCp1Z ze+LCsMSMVRINV;QcNjR2C|ZZvTjxAnUMbh`T4shc5~Q^Y-{xT_9isw2cb*GHKM@H2 zTBAWDQxa}-C|POcOhRO~1?YLy5RWFR)kX+E5h*=EYb0kGmoDw3eJf8Zk*rLd>^ma+IR!+vY_eQNZbynW)-9bJPZQ=!C2fF-!b^Fq=-0 z8Eqf-$b@Yw+`zHbFVtjE*r{*3#Oy z)wXT45+uw}{ao|kg>hyUZI7jPr$bff49fkbkXLozz?Yty8kHjJidhfgBk;Ra{vj&T z!TF&rRMwIPCh=8b{^9S*tfjfe{J&s zh2@42vr2Z=MXPR}PCq|!+!)i1p>Al+PP|3%54zf`j|b8ku|rl`gpePVV<^rk?M0mB?@* zf^egbRJO@3o>vLlQ5%M|a!sD5t!n*ZzlGi%kg?i}Q1LdF#dxY;v45`vy1u@?BA=yJ zuy#EY1^uI0p)adk#ZjImu@CfF9loS7Ul#An&jsOH4$*XPcOzyOkGsHSp;-i# ze7nd*a>^Vhim_6A-d(YL9$Iu;ZBQqdfUCB==-nmT{u!+K#bO?0T|b4VK?S|hUIv<3 z_!Dm1`i}Pv{-~xj<`AVpRh#uqm5UMQ;aS6PvlGg|0R{;`XU0Y8H`tANtBW+P5B&~L z=ZKyI;K}r8>zzj=|JdHsj`gFJqQR5L1yf=K@+aiXB z;`TowGrC#eGu615WHTDckGQUkv0h4omlK6j=M(48nnvP7&JjJll!Pk@LSjYj1tK$!y@%dze`Pu5u} zW*p~2ijFAdi7w9Mbop$B=PXvQuZw$o=3JELTe<1hDY+lXYBhFwq=Q?3f%QY8m9pPr z^2YPvd{L;{Zijd#K~2>Mw4S3#@#Xd-lK{~`B-UDv#7d;6aYoboo_B+nmGZf6@MYG| zsgy?lyZy+_K@vwHYMg(nL?@ev1nh>}4sX?@zc64?<^YusPK6c3f3WUM)4CH{jKG7}oa}eY^3h(i^F3t*0d)zrovod?;&|tf#mX@qqILs{Hr8tZIa46BSWE1LR!| z=X}h6t;{@ZPt;5}nMYB52}4mm#}c!MgGo|AydrkO=0sFO89a;7S)yc0O>%dHyMr;$^qT#}XUQGvM< zn@My~ti*oqim=;Po{8FE$s%>O2L=;_MCEWTC^7oLE5L%<(t3fi31#fV zu5&Ng9b#d@RoM64!iuXT%hk1j{Ak)_m zHu|qint=`KC7#;B3D8V}NPOM@)83hfL;bdYzf!5hRFY(w^sN*j$-Wg8Wvhhjl@Nom z55|xbm9@oAmh23LG0Yf}FUp#2WSK!?ni*y+GX^um^QrHB_w~E)`#GN9aXiQK{P7&m ze{+}_^Z8uY^*OKee4nrLyy{0}$@#h!h&S)I711Be1QDzn^$IgBzNL-`rljJEPMg(U z#=HhPdl(xA7bW5z_d4G0xDs65)EQuJl~1v1QlR(l3sI6J!0xe%ZW(~7#LFGR0mp!t zmY@*lcK`U-HJzFQ{}Fz_riV-!JJpPUh>-$8jLv!IVS!h##QHM5$u542V>Z^4)kW#} zuhju>LpqxMn2H(iOl8?Nf^7H#zV$|I@Z>o`=~v_$ZEKEN_UZAM zxt4OWV-gH#Bf=MR71pkNgg>R%@o{pjgq_WUs~}PSrT~MiPWVA^UmFJ2yZA(0Dz7aB zR=yWkqT~=_Tl_U@TNY&s#ABD&75JT?AWQBJyjvk!<8j=`B)~vrs;@tICDp9uP6$nw zu)$Q}vBS?Lgx)j-&Sbph&{C(XNYG#%D?h<~9vS8(y>BKg2i@qqc%&^aop)c;zL3kw zzWMM|At8%h9}as?6=G&_lrHUf@xI1+X83`s<@Cj!<%+5&35@KsfFkG1xdzTsf4e&M zgb@oZ0lGH49X+VGW^Ql#=*jn&MG12JMcm~b=hXbN5#bhos~-I)^D6M&af5DUP%r0` zcKA>WlTg^F)BO$YspNsLwdFPu-HV2l+XH1aF=#7oq<*>u`Oa}tT0(=hex)m_e2h8= zd8fN}2aQ)w6|sbvYeCU#8QU@jqnFam0SUjgz*(s#M4#8%Et=%lZl8~@-e5l*>1yUJ zY`b8gZ%sPrTyIxPHJVH_Itn$myJ=}yMRB8f)2^P%1JQ;)7Q|i?g8o!N^6moLvC_qk zupxir#1c_qNOLHhGoKKr{jKMyr}J@nlP!n%%YYP6V(6Tmo3mL~F&vrN5!LzKCDFVD za=t27UZ7K1JGY;Wce`SY)DVPo?`hdQP?Ae>ja*ehB#rMF^U2c(so+b>y$fmzTIJ~m z;~myhoolr2(9j{@-X!J^g)%2@4^@s7JeE4*au8Ffujf^pALc{9QJi4E_VaO4KA9KK zA}HwnaV^ewqfSxoYbHOTGZ%3a1YYNrKfi+qFGc(QfVg)udbF=)?%v1mK;K$ejNkio zltazL;aRW4oLYL!OnRj!qQgpg(igG#CLrzos`JUk8Z=|A_-2J1UpFoEW_%_Gdx39p z@G(OMvpBh9Zfs7Xt<$T)ef-I{KfUn?CD22n_H1`0z4K-x^YwZssdtPN(PuL}(PN1nqV z^Z0E8x!ru^m*++Y0@>TT>?GV%10rZ2;|z)PlOZZa$R4gN0Ok0bpab>nBjjaoydC#P zcvZ|0*Q z%Ca_S`wq_HUiy$ObkxWuVy40GDsg|Jn}?ic%GtJ}qI!Mt7O9;rQv$T1%7R$RiEKbw z;RlT536Ze{ZXOV{LIbzIap)b^puOWjZRDx)=Gz8}%#{a=#QN^62>5!>>WOM1y> zQ0oEiQeX=29(xhvqp*sKr-FSpXuw-^^WP7g7c#LEkh;9~bZV089kjl3$ADCLc88XI zEbZ%LVYd+WzQgLuBZ<*9=UE8e3v<<=(O$9+kP9^~GV)DOPqw)OhL&-~Tov&tVk;KF zcM;__vWe!w=fw?HCCdPYmy_g3d+Z;&qD+eJd_bW)#@m^eq5uhWrZ#%ahfyQvU895~ zc@D8sAV-K5bwuxPtyvmKDwE25V5oQJ6c7)8_zsA7UeaPW=*unL?;eW8@|(csu@WIl z1C?=>t9UitXlP}kbi^yz@UKgh$#cP?az8(|ISupk&*oz@tMf>M*g7kj zks8;W@ig%!fi*R8SJ&&15{HwMH3#fPa}^F+6zR2yT)mG0qZG#dfN1jS?ym)YIyJ*hS_om>RX>Q=(hXu zYSXeBK7|pfdlsyi2cMdk$-svKQo-l8f2IsiDEyP?JUd_Q{1fR+q7W#Q+Z9&EC!AsQ z+ZC-JXK9%}m453nBWYuvGjb=#dfwYtIX~SEYy^vHCA(@8T;Pl!#}wJcsopq?DrMHe z)*?{A*jq}Pvr_r&nVNcGOta`1>^*j>7g2f5!~Q@DK}#IKBg+zKV$c_^b5aGslK(j| z{}_mrzw|~R$@MRy-q?U@-Ye*argM;5u#BC|v6DA8dBFvLh0;3Fa`O7ne8}ZLFYWnT zX0)w;8@!}Zc;2Odcb7s1dW7{xPNO5NfaYQn+|eIQ87o3_;lX8d;{L4qVka8{;t(Bf z3QqU`w-_x0p{>n|vq+h8*UDLS(5c`f)|oaW;KP@62F)}&z3}f@2f_^OQ@S*sHN8A8K48x+I+X$>H#7IH{Oxs97B7ovh(9bYf5qJ8IUV?IFw4$!Ly zb+%#Uh7nm99nwzbxJu?tR-5yxDasdO9k%?+A&?q6nY7fr6rAlP2Mb~x3EMB-Tr0_S zD;L`D{rt&y-QW2eN}>9i(NVucVtpzjoC~vV+nA1pMk`89Ok;8W?GV8qVCqsR`Vn>d z71S*b{5017l(OvbObUo$eZHRCQ3-=eIB>%p_4l+dZ9>(~=lod_KLUeB}lH z@P(Y5l&Kiuz9?pFjbQNXfE1A)J`eahUC&&vst`t`-k#w0>>@u^HGaHlB)aDV=VUOm zF;na2fkqewRxxX7rHRSs06rx~Z;|^Ed-1*Anh;`)m2@cmoQGCU3tR376PhI*U<2x+gZKAhR%m@Ln-0dR2B~n1zY^J1G z=06AQi?RsB{6?L8I#*o|Vk4=mh7?8QXx&z(dIuqCCEVSFhb+NV6UFGT1Xix=;4 zA1`$iv~N?ye%^WbZ;>Ck^XKikv9g3Cevg>ja1V4V&|Pm&-q(;spfGy~lLUX{>7}I; zxCh%d00~>E7%y#(&g75s6Rb~Hrra4n0U)t;v12raq`7MVR8g8S&am4>rUj$@bpppG z>Z;Uh$KYT0!GWC4!$lxX^pAT-EMe6<$8+`K~;mwHT}J*q)g{tMTMz!M4>7 zN{^3P=kHNT71qPZkw49tr$OSZ%<`Wn5=>-Z<eryokgdyr~T)_CvFsWG$(%*?%HHV_6Y_3Yf{*k}Azd8(68Ict&C zPtexRYx}t{*4Y`{ z+|shlS`uq^Z1*&FJ}E0=U~B*? z`{Wb=@$6D|>XcVe%M+$wwQsg7Eu_5xd>>f=H~5SH{h8SmjFUkZ4XvIiY_K!DW!ImL zNpnW|+3j&3LZZ+^C76bbLWy10qe8pZQVUUK1?^TtUn?CnY_4s;DU)XiP*HL(%rdSU z^vF~}o&jlQbC)>m1N6C|tBBEC1RtXreXwBYkc5)qwPYOHKV1EsOSP|kLQ`UCs&QNgIITotnn$XWD`HMp@5@kHIRAkPq|M1?&CBt!WFx`GDDh;J38wMPc zbe!+^aBT+;3Ek;noqI*zU?#rY(hd?YOpznE1o6B1rqy+|m+h>w_Y)&lIEC`n0-8Z+ zxV;zy&kqES?av-F>MM(5OR!v5wK_l?>Je~QeB@@2ONXFxJE|dB<~Ci@YC0I+Taf81 zQbzIS0fGrKX*EUYOV%j*=MRR4x88Rn4xjZjs3_~JjQhqD?mkpq}1;bb}}F zK9RH*0GmY~Dr^~doN!fYCFTKXSDT4tIj@g_5%_>r&>79nh8#F8RN^%K?&X%;!atVW!kgeMTHy#q)Qop45MPHccsvbOq9VW?>TP}wu`I%+tu^tS!o0rJM zkR{&EdT$;6*dTSW^YGF)o`{UKk(r|0`v&o%uV{yk-Hg-)q@>wsmb^}_B_AL1o0=03 z0k4Qn!+El2Ca=xsTwTyywXHc!>~h&pi35nTt3P$b)ld?c9H&;LCG6(U_C_48B3#l! zA!;mO4PYznH(-hJe0fykeyh-FpqNvO6hE-qu*&7Gz7>6e}#lbU%KT;{8)n$Jm;}QY7riW&a=D7OL zS?>csmpa^+Xh`insi<9l(cjqS^)-+F=XX*wlMvVzjNkAdTZfMYn?AC=IfQXG*P!2U z$kjJ17!4yQNMtxQ^p3r%QS9zB5ZOi`_>yJa&eL5~s%oLM8zmlz!hJpJ$k}dfo{!o3V z$Ds%>99mXZWol74f}3t^Gz_c!%tvXrvMjg7Kdb1*f17K|yc4=g_!atUe*seq)I^Y+b{x z)!yr8)<{WWJn|G?p}KPQFJ+Yf^!rT@kv#x|Z|-QAJ*on1NatICH6!MzSVY9H2Q5X z3rGJ;Z_34Hn#y&1r6QG1`To?{O|VX^Z5t>GGzYb-8} z)|UBfEMrQ|u?0<0g0CimsgM~Gbj@)jdb-xJAClt~2Y}_NsP#L#l#pLJmzeD8|BP~ zf}!kG;Mj0Bw%BTLCX*OlbIQqn5n-l>fy_;bw71d45(sgp)uDW zB2wEW-jHHFR7N>c#oabH+ac5~cKpDfKk4m!wFZ>jFXzDVpUy#|>z_Rm82#9}rnX%t z@ATZjF4@=IbTTOQCx$w$0WJ{&S)#%VKX@2WLC`DkQD%+B>4Dvnxc6RJodL*VLyDWL zgQVw5;!=z>+q#9)VKQm3t0fUG^Y8x{OG{JzI-Da zq;(vII|#QC9Y}hyb0nRw<0G~7R&VuX+>;Pt_ua}l%45<$w`Tyi`@Y?E8W0p6_HJC9 zO=5&6Cl%czD7ZAvW6C0VaShC$EcQa2OYoKfce4Vo58N~jXk({+e#ad^CU5N`-#aC6 z7o7+C(Q?_`TC`T!@d*%`zz6mR2EhxEIkyF-6JeoV9TPhPnorF^$`ECt4*N9rQ9}n&;&GecT zl#Pl$-Rvg50CKBwhYEnv7bfgM+DI!Vb#Pke-Tc`sryup*&ChX1{Ai|$hibB3WUT_Q zZP4GYlXRYNYd%O5*?I^l?A-kr2pHeDmgzqtr$`b!PRKom_SAl`Q-5khtpo~)UW~Sk zYT3UlT@M~aWiGUP#|!MV?wIO0OAMTU0An3}0ly0*I+?H4E&b~H&50VGa#aox63{EU z&Pm=g9q3oko!C_Zv95@V89gHr{B{4ZRAFaMtVuHKbJiAMk3Grrd;IPLW^0QMlJ} zeHXbvSa14De!aL4;EXS!yMFpBJ#K~LiP|tDSwP^4toO~W_X!WBsVTxkivYNE%kiy0 z$;gdq8|Z`2XyTXfS3GNE{kO|G0KU2N?)nT(MQpp?JE-NV7=K=c>Jdyzsfv zTXu&nffaTZ_Y(!z9_A+XKLXT)&vzD7h+l@*7c)PNQ&oTNG0i$x zbW(NUkWY)RI81fv0O>Qc7IZv|sFD(8fT-UMU zB6j!os&Bb)?=Yt@thaIe#j{^j?e7|*I@PYukANF>rgPkxP4~~(q*S$B1vE|riGQKR z_mFioRvZ{vN$XESoh!b8Q27leHpJ>=QSE`IeE&65=3TnhN)GO>CRF>-F#fdue4tIr zGl?zjqPlC0zlz)e0M<6cF^bXVNAKInjR?3Fwxl3+rY(wb?4)fx+IYK6USr*p>jGQ) zUpZuH6>UuMg1<)dh0Kq$@X6|_mg%0jS+nl0~*e4_pZpt?)wlSJAU$(&Bd>v4^YqD zV$Gx7WoT>-Z@e&8`w*)s+*exa2V5t8>7Z`lgt{)08IIVx#dAx*b+CN4=)aKr;J)S@ zJZQ9K%etP&f;D!IHkad3ra*a;de`kpKDUhKnyfUxAC(8tK zcz)iz4~tv3GoNk$S7!eiaIl#<+;xSe`$efKFj_&ZD0;LOIpOGU7Y`a%U<1vs&)XBW zFV}LXfV__-r;G`#<%bE{+}~o3FzJ$B@cDUb>OD-1K6+G7!yLx68ytNvd{&ECO)WmESS`Qx8F z`rmT|VCTS-rLyh6F1ig*{VU1ZM^Jz9-V-|9=yh(K(f5B@_G(k6rsTwp!G93tP%wQc zY`x#?MdOh7X5HL{?SRX_JRaCg1T+rM12As93WG^+{MW*feA{Is>kVf9yhb-*6)0BB zZ>I_DG0_)|{rQ`uYtJ*uI4gVOm(wCMdL)zl3BPdS}U*L+l^;a(xylH zNjl%Xb<#0N1b$s>WWFWYzjp)oZo>#5S@&w*QegKC5u;lW`ZqzYtps`MpAD;N@1-2Y zVFsBFC4+dsiKShkaxg4Oj10GeI4h~L-ea7BQHciSU#k%9B_jZ72od2tFjTTe6Q_vp zegnTH9Pim@=WO@3E^a4*`ANY}%)eqPk6})0> zh!XPQco@GUgkBis*}C?vVYOseq#|joWuNj$*ae7l>b|L+1bza~HIGcNn+U932oqVG zAWzDgyzPpZW|_dgQfC#&y&L5Nnt`hre(V(hUMvt z0=h;)mCpRWy8zVrYH(`OjX#of!(Zo1HorcuGDfUFat%d9oFCQ7L)s)mOi$K^sRA{N zXIcKi?D%C@cG>XA)b@Ta127qW(=b`Pxc{VBI^B8d)nt^2UIm4i)`oj1S`*geE=zz0 zJI0(s(VbX_O@bT-5i>b)W<&*iEaL$*Tff!7#qdW?cMBrg+?%!3ey~C3EoB^i)1Md- zu4`pf7qJ04+!Yb^iHEm`F;x-`4}APedQ(Z7lgp`rIO(OaZ}$u_!e3>M43$)c83-Gn zI)AaK62MBYQont<%%tsh*9pE2F*2m{0NipJ+%vy~2l>S@lF=*SQMAAk?`tuNHv!r8 z{xHZ|PTAK`XsV~DcjUb;<1ql=NN8y~Luy^Gj_0}XUF>#vgU4INQxi#?1mM*XnNR6U zJM?ZH&xh@5~9KL|28fAlpK|wjcfYG--m9 zZlrJ7o$Rw)9Un<*p{@!gdS7&@ms=9tO{OUe#lLo&RKB<*nLoQFG58a?#G`!4q%{9fS*Q{EMcEGkcX-q+~>DFh?jVSdK(DVkKATgA2AJ!_*OOL2LN!C zp#))Fd74eRTVr(Hl1MjxSz9p8ScNH`cEifXeO1{G$?fUay#I?pK03BB#sO-!Xl(`G zX18oP+<5iU#apn6ZW1Sozc<0Y-k~J{vW?OA(dDq`Rj{!~UyN0{ALHB8rFWCv@;C}| zX_-##jcjds;W@6yPUf}F#+B2$aj~AlU?LZwDiL5v=2G2Sn_q)UQ`El8neZF6mJ5;u zZdgfEkgA|clrH6kG(AV3v7)NBY45ZQh-~$We~cYe-zq=$^6>7FrUbFwpC-46533yP zn?p>+@Ap3jl-0|Uox%N!WEe`BP)pL#;nl+^UeOwO?w%=gu+Lb=TUGUto=xL&XC?NX z=v;zl_x|<0oe^7E;n$v75buZ_BYd1YCmg0Ci+SQjr;7?|XYvZ_bH}^1s<2o#Oa1Es zLWK)`89V`0lNm!JkW1zstt07&=+U7^mDocV+#ZUf#I3#JUv6$})te_J%xJf1alCud zgS`sa56N!$)Jfi%obWJu7qPt2OVqv6^O>9&e(G>$R!SKrS?2GzF7x;JFf!(aq$h`Ww%=eP+ zU2*~~L_5IBu|f0&kw>qMF;6IDR(mr41+H%ZCpP3Rj?0Q|6g`pg`Ao@Mh1;(3glF-Y>ooCprdN{^k~1ZlAi)n z3&v|5p~nW^Ya5_uuyU7)cKH-ukOoO~Pgl_#GX62+n>!Q7R#B^}8fw`oH-5p3c@j(= zLu)d;BoDtdI%qBD_v#OhVg1lBXH#E3};eqxva)a+^O3 zZ|X}?x#XsY*+?t7Qjzc9IZTKrC$b}u6I@EjodRr@V)$@rPWf2QltuS|guGvDib98d z2d(+V2O;6UXxXM299?udp7n-t$4jYcWY%V{-HU|#7z=s3VmQ?iV+qt&3B~%MfdX`F z8<^>Q0DMF`z*QTEa6X!cMYgpprSkq!#hmYr4u5F9_g!~$Ja2r^uL_4qK!>%wB0z2U zkm5J>PD?4ni5k@XW{GccAGS&T1f<}1TG*L0iOc8W>dwFEKf9~kA;~AN6<#z$cZmHItS4?H_hDv zz!HhVyK}Gj;$|j|SF|YI?DjTmk|yVL!}u8La>c=RXPgwS@|q$IRNvjDvKVCRO)R=j z3Mrpav@MH@-`U|F8S^KqZ|eRgk5MdFbg$HxSe(1k)FM}I?r@<-fmZqDb!jC>3ZItX z{FU8*16pFaOCyyjo&)HYGbmTI@s(Y&HeHVc`SI7IN(UJUw~-^MB|KhSeZRL+~7HoM~-<$SAqVA-e>b5*$t zQ6PN;c1p0SI}oV0GY?sCvWu|-5-o2xg(S2zF|`7IC3B32>B)Dq?`VL?i_6qAJJ4sy zJ8>g+Z|sBfl^kooinqsFHCT27iM{*zV`C20G=9bDWrj!b>uzKJ(QoD^Y{g0XQxRRVt4R@n3LvB~5^{!cUur+{J z#>l_iW1#vWBoe5a`;j8ifW7F?R5Z6!G=r$KafrTOzWyV;;Hd{D-T*1n%~ag*(g0Ww2(< zPrn&`;a$v3AY7fxy#l!7?u44Qu#~f*BKx5`Hbom)xy%b=*&?y#C8KVSDjK_~C$*`P z;&b4>7RD<~X`f#_ta;!%>6-a1Is6;OWqvy&NDm=AX|h*B%a$IH51xbD`sd6$3lt5HmVtjBGSsb$?OTU5`o86&9?)qTTe zli+PB=Z+DNZE~+*h`3rL*?wMD4yG4;mXY>>6rj~mgo9ZYs~@JYjXLJIb}z zQa`LrRC8GG?k5bHp9N2e&Vi1kOoX#m@p{U+`^%kY_NVcXWJLP9=)H35O-x~ytN@yl z{?7KW+&;f!l0bRZw->cuN6rIQeMsAkMWgnANgzjRJB+fQPf?=N?0Gww*YZLv&sT@l zm7oiFIwgrv=^w>_Q#c)O=JZCt43hy~eiKdb75)g5|oBBy(S+fm6)R%uuIuie?4@y(w>oaRIz>ghI0j~qRvPE4TYl{2 z-NyHZj?u*ok88Wkry+o9x;E%l7CJhTA#-F-CmW7aAQU+1l&6PnG_<5G7?^f$59yuv zlqfmFl-ggP2KZ1GG+gamcrzs)!jvEbKJYi5jD%kyh4Hn^%h5^u7c35JHaKWg8!9e4 zaKWiigN-2kLBt%8C7UF~*WAN8mPKFeq(Ark7{-ifyQla4lHOY44Mi%)Xzpq%Fcd!M zz5X`vjH?rSb~?MEaq9^UUqv8Ud)~+g99mn@!?3;bE{<|NIVWOw0}%~`+$ZHflFoB< zY3yEC;8{(H@y9d~Sff}f?*|2LErqi%c||ZcIW6iakq*=k@x{5F!s)>d%^aJbgIRM` z@;G$!3p({}v8m{er-9L%wxTgq+OVR=*`{(YT51#_+aceduSB|SP7$W4}Y zsSACH{O={Z_&=CZ{Ejlz70X8@x$Q+5dPSc{m2>Gma=0!etZ1*E9wvp{+iO%k>h~jL z>aky;KfBH-=S&V0@BsCWU{Y>S9-J(IBLG9|0;5~f*NrhJV5v*T*_Ykr%Z zcL3{$JB`--FzT3MPMbfNWy5TiB#8IBV~c!w~{pNUf9v9zAi5ZcTVx>4|{Dq@otD%UL^#sdGb zRRAj9MS_M&?ekvS9Ia<;OrEy>0(JV2?*%+)wlQUEgg@=q-{hHntL70U29J#IzLcT8 zY4;K?6#qJp?_W1L`i-&4U$0Z0`w)qKvkcp|zc7B&qu%1mTk~vX0^}P!%>*6mkm><3 zRy5QQR5p=5zTqMs>T;=3cw`2g;h`Qc>{6&QtqOHn!h z`Tu@h^(FU*9e#EuD}f$Tz#(Okh2TM-_H*YI$v9skofImISgr^j8=r7sw zgpGV{Je0W%;(g0DjjY%x)mBnrF3S7Gquq5`cXfy09wt9Hf?xjA?J4iqoBRTqw)b_v z71hJ7!fTq1(O``mJrvEX{z+IR#wE*YIb32Rs^}D)a8rQ!>8?Q&H#q1uwl+E=z@VIEJ*pA5l4B`A4bEf&?J)c|sw5cYQ_p-` zeDNC73T>-W-14yX6tsF5U z(Z-|VdAsy>v4b}*hsl%aY(Vuwk9GI(hUQ3`wbCv`b4fFy+a)wrS;Gi}gbmIRMf0|1 z7_O?PksMXQ2C0>s{HL`$dMO6zGJ9dD(edR%#UNQ8_@4T@i3J1`#e|3c@c&qVjwR70 zIM*SVjmuEsN2}(K87}n~XqwySld&C<-NM)gklk5Fbc7CwGVgR1%#Fsz57}uu?4sd= z>Jx}$@#e?#69})58`BwrMO55k=!uzNhqX@xm#ztt=Y+E4nEO=XxK_7(2Cq1i6!r&M z5%(QTTIylkoR|#vU5{Tkrz1SeQL4%tZvT_{xG9M{e4jAS8PeIX&03S44Sg!`1Rr*b z)DuRnK9c^yt#%|~J==A4eOBejxr@w4;9C)FtPXaXA3S6m6&gA`+U8*lv+i~57ObyX zYv{>%KTo%-(GAYYXQSI4)}7o9U_7frIBv%{We(B|gB4rHYqF~K z+>Tpe|DOjIK(uvKOB%IxzEx*$lncA@-8F0MbpW5AYLcgF6{gpyd7i(W{$(!ab3nKE z<#Fj4E0*R1%rmU)c+S=D96T*-#em7a!hFNAV8&-mpZr4fozKclVt-8WEKFxZ&mX*f z=v<%&@pfQDBhpnw#VO?8_zo`ZeHb2qzu8}yX;H#6X@sb)rn8(69$oTd5qxXU0Y|2V zGoeGVY2L7?N9XIVO=r+@uo~ZFWj3W3yhp-4j+q?Kt59R5YSfHOIVuK>xceS0l&t#T zD!cx{<0@z((l4w|__+hD4I0&4h3@K+hgUc+Nxe{%ZMUbcy3kg95zDFeJ|EdTxc1|T z_v*CSMnEHY@f48;)rL_F?Ye<{oVfh!&wf}|YgYOpW)2^?u0wB#nl!q7iQ|QrjVJff zwg=E_dB;3AzUR6W+%Eg<_EAZzC@zq{wEvI5FDgJe3{lW{_o~fXJu8MIgW{BfE!Js*N}Ou z^<5-S?XZ7aVE^Y5y7R*>S(l~#0Jc$LW+{l>qkVkWU#$jLI7>Z$B&q|QkwIPKf&bhA zTdJ$S3Ta%rltJu!{wCy?M|b_@IA=!14*@iz=jj^vSyB;y`B&dTpi1Yc;?B6 literal 0 HcmV?d00001 diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml b/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml index c5dc286b5..d5c88b4e4 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml @@ -33,6 +33,8 @@ href: uwp.md - name: Setup Sign In with Apple for PlayFab href: apple-open-id.md + - name: Setting up Xbox Live title association in PlayFab + href: xbox-live-add-on.md - name: Integrating the Universal Windows Platform with PlayFab href: uwp-integration.md - name: Setting up Playfab Authentication using Anonymous Login diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md b/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md new file mode 100644 index 000000000..596edabee --- /dev/null +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md @@ -0,0 +1,64 @@ +--- +title: Xbox Live Title Association +author: antnguyen +description: Learn how to set up and configure scoped token validation by linking Partner Center product ID to PlayFab title ID. +ms.author: antnguyen +ms.date: 10/09/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, authentication, server, partner center, xbox, xbox live +ms.localizationpriority: medium +--- + +# Setting up Xbox Live title association in PlayFab + +Learn how to configure scoped token validation by linking your Partner Center product ID to a PlayFab title ID. + +## Overview + +In this tutorial, you'll learn how to configure token validation by specifying which Xbox Live title tokens that PlayFab APIs accept when they use Xbox Live token parameters—giving you more control over integration behavior and enabling scoped token acceptance. These APIs include `Client/loginwithxbox`, `Client/LinkXboxAccount`, `Client/UnlinkXboxAccount`, `Client/ConsumeXboxEntitlement`, `Client/GetFriendLeaderboard`, `Client/GetFriendLeaderboardAroundCurrentUser`, `Client/GetFriendLeaderboardAroundPlayer`, `Client/ConsumeMicrosoftStoreEntitlements`, `Server/loginwithxbox`, `Server/LinkXboxAccount`, `Server/UnlinkXboxAccount`, `Server/GetFriendLeaderboard`, `Server/GetFriendsList`, `Server/GetFriendLeaderboardForEntity`, `Lobby/GetFriendLobbies`, `Server/GetFriendLeaderboardAroundPlayer`, `Inventory/RedeemMicrosoftStoreInventoryItems`, and `Inventory/Redeem`. + +## Requirements + +- A registered [PlayFab](https://playfab.com/) title. +- [Partner Center](https://partner.microsoft.com/) account with an Xbox Live enabled title. + +## Partner Center Product ID and Xbox Live Title ID + +Start by navigating to the product page for your Partner Center title. + +1. In the Partner Center dashboard, navigate to [Apps and Games](https://partner.microsoft.com/dashboard/apps-and-games/overview). +2. Locate and select the Xbox Live enabled Partner Center title you wish to associate with PlayFab. +3. Find and copy the Product ID from the URL of your game. + +![Parter Center product ID](media/tutorials/xbox-add-on/partner-center-product-id.png) + +4. Next find and copy the Xbox Live Title ID. Navigate to **Xbox services > Xbox Settings** and copy the **Title ID (decimal)** value. + +![Parter Center title ID](media/tutorials/xbox-add-on/partner-center-configuration-page.png) + +## Install Xbox Live Add-on + +Go to [PlayFab Game Manager](https://developer.playfab.com/) page for your title. + +1. Navigate to **Add-ons** in the menu. +2. Locate and select the **Xbox Live** Add-on icon/link. + +![Xbox live Add-on](media/tutorials/xbox-add-on/xbox-live-add-on-page.png) + +3. Use the **Seller ID** dropdown to select the correct Seller ID from Partner Center. If you don't see the correct Seller ID, select **Sign in with a different partner center account** and sign in with the correct user. + +4. Use the **Product ID** dropdown to find the Partner Center Product ID that will be linked to the PlayFab title. Confirm that the Xbox Live Title ID matches the expected Xbox Live Title ID from Partner Center. + +![PlayFab Parter Center product ID](media/tutorials/xbox-add-on/xbox-add-on-installation.png) + +5. Select **Install Xbox Network** to save the setting and restrict API calls to the selected Xbox Live Title ID. + +![Install Xbox Add-On](media/tutorials/xbox-add-on/xbox-add-on-installation-validation.png) + +By following these steps, you can confidently configure scoped Xbox Live token validation within PlayFab, ensuring that only tokens from designated Partner Center title are accepted. This setup streamlines cross-platform authentication, reinforces title-specific security, and empowers developers to deliver seamless, trusted player experiences across Xbox-enabled services. + +## Further Reading + +- [PlayFab Authentication Overview](../authentication/index.md) +- [Login Basics and Best Practices](../login/login-basics-best-practices.md) \ No newline at end of file From 49db015351300f78b0c590bc42c5badc355f3f30 Mon Sep 17 00:00:00 2001 From: edigonzales-microsoft Date: Mon, 12 Jan 2026 15:28:16 -0800 Subject: [PATCH 05/76] Increase Acrolinx quality score from 70 to 80 (#2763) Update quality score from 70 to 80, the minimum Acrolinx topic score --- .acrolinx-config.edn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.acrolinx-config.edn b/.acrolinx-config.edn index cddebf863..fd2404316 100644 --- a/.acrolinx-config.edn +++ b/.acrolinx-config.edn @@ -11,7 +11,7 @@ } :scores { ;;:terminology 100 - :qualityscore 70 + :qualityscore 80 ;;:spelling 40 } } From d0d3d89a46a1966a66d38ad4b72ac7fbdec614da Mon Sep 17 00:00:00 2001 From: Sebastian Perez-Delgado <46662157+SebastianPD@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:31:19 -0800 Subject: [PATCH 06/76] Update release-notes.md, PlayFab Party Release Notes [1.10.13][1.10.14] (#2764) * Update release-notes.md * Update release-notes.md * Update release-notes.md --------- Co-authored-by: edigonzales-microsoft --- .../multiplayer/networking/release-notes.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/playfab-docs/multiplayer/networking/release-notes.md b/playfab-docs/multiplayer/networking/release-notes.md index bb4ea91ce..0b48370c7 100644 --- a/playfab-docs/multiplayer/networking/release-notes.md +++ b/playfab-docs/multiplayer/networking/release-notes.md @@ -20,6 +20,27 @@ ms.localizationpriority: medium > [!NOTE] > Support for 32-bit Android platforms (arm7 and x86) ended on October 19th, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using the PlayFab Party library on 32-bit Android platforms. +## 1.10.15 + +December 17, 2025 + +- Nintendo Switch 2: Added 10 second timeout for webrequests. + +## 1.10.14 + +December 9, 2025 + +- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has actually expired. +- Android: Added support for 16 KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). + + +## 1.10.13 + +October 14, 2025 + +- Fixed an issue that caused the microphone to not function properly on iOS 26. +- Apple: Added support for Arm64 .xcframework on iOS. + ## 1.10.12 October 6, 2025 From 1dae0510577720f4c0dc14793ceae7873f30be00 Mon Sep 17 00:00:00 2001 From: Cindy Johnson <88344363+cindyjohnson-msft@users.noreply.github.com> Date: Tue, 13 Jan 2026 10:51:39 -0800 Subject: [PATCH 07/76] Update master_player_account description in Available built-in entity types page (#2771) --- .../entities/available-built-in-entity-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playfab-docs/live-service-management/game-configuration/entities/available-built-in-entity-types.md b/playfab-docs/live-service-management/game-configuration/entities/available-built-in-entity-types.md index da010037f..ea220e468 100644 --- a/playfab-docs/live-service-management/game-configuration/entities/available-built-in-entity-types.md +++ b/playfab-docs/live-service-management/game-configuration/entities/available-built-in-entity-types.md @@ -53,7 +53,7 @@ Set the `ID` field to your game's **Title ID**. To retrieve the **Title ID**: ## master_player_account -The `master_player_account` is a player entity that is shared by all titles within your studio. +The `master_player_account` is a player entity that is shared by all titles associated to a given namespace. Set the `ID` field to the `LoginResult.PlayFabId` from the classic API. To retrieve the `LoginResult`, call one of the login methods in [Client Authentication](xref:titleid.playfabapi.com.client.authentication). From ebc1d90b4f2d9750b9febbd37301705bbe7d36dd Mon Sep 17 00:00:00 2001 From: Jason Sandlin Date: Tue, 13 Jan 2026 13:32:49 -0800 Subject: [PATCH 08/76] Bug 60687305: PFGameSaves SteamDeck: improve docs based on customer questions around conflict secnarios (#2768) * Bug 60687305: PFGameSaves SteamDeck: improve docs based on customer questions around conflict secnarios * Removed some duplication --------- Co-authored-by: Andy McCalib --- .../game-saves/conflicts.md | 202 ++++++++++++++++-- 1 file changed, 187 insertions(+), 15 deletions(-) diff --git a/playfab-docs/player-progression/game-saves/conflicts.md b/playfab-docs/player-progression/game-saves/conflicts.md index 327424dcc..f152d206d 100644 --- a/playfab-docs/player-progression/game-saves/conflicts.md +++ b/playfab-docs/player-progression/game-saves/conflicts.md @@ -3,32 +3,204 @@ title: Game Saves conflicts author: jasonsandlin description: Game Saves conflicts ms.author: jasonsa -ms.date: 07/01/2025 +ms.date: 01/06/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, game saves ms.localizationpriority: medium --- -## Game Saves conflicts +# Game Saves Conflicts and Atomic Units -Save conflicts occur when the same game data has been modified on multiple devices, and the system needs to determine which version to keep. +## Overview + +Save conflicts occur when the same game data has been modified on multiple devices, and the system needs to determine which version to keep. Understanding how conflicts are detected and resolved is crucial for game developers designing their save data structure. + +## When Conflicts Happen + +Conflicts only occur during the sync operation (`PFGameSaveFilesAddUserWithUiAsync`) when **all** of the following conditions are true: -### When Conflicts Happen -Conflicts only occur during the sync operation (`PFGameSaveFilesAddUserWithUiAsync`) when **both** conditions are true: 1. **Local changes exist**: Files have been modified locally since the last sync 2. **Cloud changes exist**: Another device has uploaded newer data since the last sync +3. **Same atomic unit**: Both changes are in the same root-level folder + +### Conflict Detection Matrix + +| Local Device Changes | Cloud Has Changes in Same Atomic Unit | Result | +|---------------------|--------------------------------------|--------| +| Modified files | Yes | **CONFLICT** | +| Deleted files | Yes | **CONFLICT** | +| No changes | Yes | Download proceeds | +| Modified files | No | Upload proceeds | +| Deleted files | No | Delete proceeds | + +## What is an Atomic Unit? + +Some file sync systems treat conflicts on a file-by-file basis – if the same file needs to be uploaded and also needs to be downloaded, then there's a conflict. In Game Saves, each root-level subfolder is instead treated as an **atomic unit**. + +> **Each root-level subfolder is treated as one atomic unit.** + +If there are any files or subfolders inside a root-level subfolder that need to be downloaded **and** any files or folders in that same root subfolder that need to be uploaded, then the entire atomic unit is in conflict. + +This approach allows you to: +- **Maintain data integrity**: Interdependent files stay consistent together +- **Provide isolation**: Independent data in separate folders can sync without conflicts +- **Minimize conflicts**: Changes to different atomic units on different devices merge automatically + +### Example Save Structure + +``` +SaveRoot/ +├── save.dat ← Atomic unit: root +├── player.dat ← Atomic unit: root +├── Save1/ +│ ├── stats.json ← Atomic unit: Save1 +│ └── inventory.json ← Atomic unit: Save1 +├── Save2/ +│ ├── stats.json ← Atomic unit: Save2 +│ └── inventory.json ← Atomic unit: Save2 +└── WorldState/ + ├── map.dat ← Atomic unit: WorldState + └── npcs/ + └── positions.dat ← Atomic unit: WorldState +``` + +### Conflict Scenarios + +| Device A Changes | Device B Changes | Conflict? | Why | +|-----------------|------------------|-----------|-----| +| `Save1/stats.json` | `Save1/inventory.json` | **YES** | Same atomic unit: Save1 | +| `Save1/stats.json` | `Save2/stats.json` | No | Different units: Save1 vs Save2 | +| `WorldState/map.dat` | `WorldState/npcs/positions.dat` | **YES** | Same atomic unit: WorldState | +| `save.dat` | `Save1/stats.json` | No | Different units: root vs Save1 | +| `player.dat` | `save.dat` | **YES** | Same atomic unit: root | + +## Root-Level Files: Special Case + +**All files at the save root share ONE atomic unit.** + +Files placed directly in the save root (not in any subfolder) are all grouped together as a single atomic unit. If you modify one root-level file locally and another device modifies a different root-level file, this will trigger a conflict. + +| Device A (local) | Device B (cloud) | Same Atomic Unit? | Result | +|-----------------|------------------|-------------------|--------| +| Modifies `rootfile1.txt` | Modifies `rootfile2.txt` | ✅ YES | **CONFLICT** | +| Modifies `rootfile1.txt` | Modifies `save1/config.ini` | ❌ NO | No conflict, both sync | +| Deletes `save.dat` | Modifies `progress.dat` | ✅ YES | **CONFLICT** | + +## User Choice Options -### Conflict Resolution Approach -Some file sync systems treat conflicts on a file-by-file basis – if the same file needs to be uploaded and also needs to be downloaded, then there's a conflict. In Game Saves, each root level subfolder is instead treated as an atomic unit. If there are any files or subfolders inside a root level subfolder that need to be downloaded and any files or folders in that same root subfolder that need to be uploaded, then the entire atomic unit is in conflict. This approach allows you to organize save data so that interdependent data integrity is maintained, while providing isolation between root subfolders for independent data that can be safely merged with changes to other atomic units. By using top level subfolders to structure your game save layout, you can minimize the likelihood of creating a conflict when changes to different atomic units happen on different devices. A slot-based game save system where each slot is a root level subfolder is a very simple example of how these atomic units can be used. -### User Choice Options When conflicts occur, players choose between: -- **Use Local Data**: Keep the device's current save data (overwrites cloud data on next upload) -- **Use Cloud Data**: Download and use the cloud save data (overwrites local data) -A conflict resolution decision applies to all atomic units that are in conflict at the time of sync. If the player chooses cloud, all the conflicting atomic units will be downloaded, and conversely, choosing local leads to all being uploaded. +- **Use Local Data (Keep Local)**: Keep the device's current save data +- **Use Cloud Data (Keep Cloud)**: Download and use the cloud save data + +### Critical: Resolution is All-or-Nothing + +> ⚠️ **Important**: While atomic units determine *when* a conflict is detected, the user's conflict resolution choice applies to the **entire save**, not per-atomic-unit. + +### Example: Mixed Conflict Scenario + +``` +SaveRoot/ +├── SlotA/ ← Local: modified, Cloud: modified → CONFLICT +├── SlotB/ ← Local: modified, Cloud: unchanged → Local-only change +├── SlotC/ ← Local: unchanged, Cloud: modified → Cloud-only change +└── SlotD/ ← Local: modified, Cloud: unchanged → Local-only change +``` + +**User sees conflict prompt** (due to SlotA). + +| User Choice | SlotA | SlotB | SlotC | SlotD | +|-------------|-------|-------|----------|--------------| +| **Keep Local** | ✅ Local kept | ✅ Local uploaded | ❌ Cloud change **LOST** | ✅ Local uploaded | +| **Keep Cloud** | ✅ Cloud downloaded | ❌ Local change **overwritten** | ✅ Cloud downloaded | ❌ Local change **overwritten** | + +### Why This Matters + +1. **Keep Local loses cloud-only changes**: If you choose "Keep Local" because of a conflict in SlotA, you will NOT receive the cloud update to SlotC that another device made. + +2. **Keep Cloud loses local-only changes**: If you choose "Keep Cloud", your local changes to SlotB and SlotD are overwritten by the cloud state. + +3. **Rollback available**: Both choices preserve the discarded branch for future rollback capability. + +### Design Summary + +| Aspect | Granularity | +|--------|-------------| +| Conflict **detection** | Per atomic unit (root subfolder) | +| Conflict **resolution** | Entire save (all-or-nothing) | + +This all-or-nothing approach simplifies the player experience. While per-atomic-unit resolution would technically maintain data consistency (since atomic units define consistency boundaries), it would create user experience challenges: + +- Players would need to understand the concept of atomic units and folder boundaries +- Mixed results (some folders from local, others from cloud) could leave players confused about the final state +- Prompting for each conflicting atomic unit separately would make conflict resolution overwhelming + +By presenting a single "Keep Local" vs "Keep Cloud" choice, players make one clear decision without needing to understand the underlying save structure. + +## When Conflicts Do NOT Occur + +### Delete on Both Sides + +If both devices delete the same file (or files in the same atomic unit), **no conflict occurs**. The system recognizes that both devices agree the file should be removed. + +### Changes in Different Atomic Units + +If Device A modifies files in `SlotA/` and Device B modifies files in `SlotB/`, no conflict occurs. Both changes merge automatically during sync. + +## Best Practices + +### 1. Design Folder Structure Carefully + +Use subfolders for independent save units: + +``` +SaveRoot/ +├── Slot1/ ← Each slot is independent +│ └── save.dat +├── Slot2/ +│ └── save.dat +``` + +A slot-based game save system where each slot is a root-level subfolder is a simple example of how atomic units can be used effectively. + +Other examples include: +- **Shared reference data**: Data that any save slot might use (e.g., unlocked content, achievements) can be stored in its own subfolder, syncing independently from individual save slots +- **Large asset collections**: If your game stores large sets of files that update independently (e.g., downloaded content packs, user-created levels), consider splitting them into multiple root subfolders so updates to one collection don't conflict with updates to another + +### 2. Avoid Root-Level Files for Frequently Modified Data + +Since all root-level files share one atomic unit, avoid placing frequently modified files at the root if they should be independently syncable. + +**Instead of:** +``` +SaveRoot/ +├── autosave.dat ← All root files = 1 atomic unit +└── save1.dat +└── save2.dat +``` + +**Consider:** +``` +SaveRoot/ +├── AutoSave/ +│ └── autosave.dat ← Independent unit +└── Save1/ + └── gamesave.dat ← Independent unit +``` + +### 3. Group Related Data Together + +Files that must stay consistent together should be in the same folder: + +``` +SaveRoot/ +├── Save1/ +│ ├── stats.json ← These files are interdependent +│ ├── inventory.json ← and should conflict together +│ └── quests.json +``` + +### 4. Minimize Conflicts -### Best Practices -- **Design folder structure carefully**: Group related save files into logical folders -- **Minimize conflicts**: Upload frequently to reduce the chance of conflicts -- **Clear conflict UI**: Help players understand what data they might lose with each choice +Upload frequently to reduce the chance of conflicts. The more often you sync, the less likely two devices will have divergent changes. From ad2f2f0f0db9569d4bf6c9f4163ebe39b2e91c17 Mon Sep 17 00:00:00 2001 From: "Valexa O." <46427879+valexao@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:07:28 -0500 Subject: [PATCH 09/76] Merge main into live branch (#2770) * Update MPS Playstream event references with changes from playfab-docs (#2766) * Update MPS playstream event references with changes from playfab-docs repo * rm added file * delete old files * update ms author to be microsoft alias * Updates for OSS V1 UE5.6 release (#2765) * Updates for 5.6 release * Addressing Feedback --------- Co-authored-by: Raul Gomez Rodriguez Co-authored-by: David Kushmerick <80928711+dkushmerick@users.noreply.github.com> * Update CODEOWNERS for playfab-docs directory to add Xbox Learning Resources team (#2762) Update CODEOWNERS for playfab-docs directory to add Xbox Learning Resources team https://github.com/orgs/MicrosoftDocs/teams/xbox-learning-resources/members * Xbox Title Add-on Update to enabled PC title linking (#2749) * Updating docs to include xbox live title linking. * Updating index and toc * Updating list of APIs that accept XBL tokens * Fixing doc warnings * Fixing alt text * Updating doc to reflect new UI changes --------- Co-authored-by: edigonzales-microsoft * Increase Acrolinx quality score from 70 to 80 (#2763) Update quality score from 70 to 80, the minimum Acrolinx topic score * Update release-notes.md, PlayFab Party Release Notes [1.10.13][1.10.14] (#2764) * Update release-notes.md * Update release-notes.md * Update release-notes.md --------- Co-authored-by: edigonzales-microsoft * Update master_player_account description in Available built-in entity types page (#2771) * Bug 60687305: PFGameSaves SteamDeck: improve docs based on customer questions around conflict secnarios (#2768) * Bug 60687305: PFGameSaves SteamDeck: improve docs based on customer questions around conflict secnarios * Removed some duplication --------- Co-authored-by: Andy McCalib --------- Co-authored-by: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez Co-authored-by: David Kushmerick <80928711+dkushmerick@users.noreply.github.com> Co-authored-by: edigonzales-microsoft Co-authored-by: Anthony Nguyen <108492711+antnguyen89@users.noreply.github.com> Co-authored-by: Sebastian Perez-Delgado <46662157+SebastianPD@users.noreply.github.com> Co-authored-by: Cindy Johnson <88344363+cindyjohnson-msft@users.noreply.github.com> Co-authored-by: Jason Sandlin Co-authored-by: Andy McCalib --- .acrolinx-config.edn | 2 +- .github/CODEOWNERS | 2 +- .../events/build-alias-created.md | 44 ++++ .../events/build-alias-deleted.md | 43 ++++ .../events/build-alias-updated.md | 44 ++++ ...r-server-requested.md => build-deleted.md} | 10 +- ...nged.md => build-region-status-changed.md} | 8 +- ...ion-updated.md => build-region-updated.md} | 8 +- .../events/build-region-utilization.md | 44 ++++ ...cate-deleted.md => certificate-deleted.md} | 8 +- ...te-uploaded.md => certificate-uploaded.md} | 8 +- .../api-references/events/crash-detected.md | 44 ++++ ...initiated.md => create-build-initiated.md} | 8 +- .../buildaliascreatedeventpayload.md | 20 ++ .../buildaliasdeletedeventpayload.md | 19 ++ .../buildaliasupdatedeventpayload.md | 20 ++ ...payload.md => builddeletedeventpayload.md} | 6 +- ...> buildregionstatuschangedeventpayload.md} | 6 +- ...d.md => buildregionupdatedeventpayload.md} | 6 +- .../buildregionutilizationeventpayload.md | 25 +++ ...d.md => certificatedeletedeventpayload.md} | 6 +- ....md => certificateuploadedeventpayload.md} | 6 +- .../data-types/crashdetectedeventpayload.md | 24 +++ ...md => createbuildinitiatedeventpayload.md} | 6 +- ...oad.md => gameassetdeletedeventpayload.md} | 6 +- .../data-types/gamecertificatedeployed.md | 24 +++ .../monitoringoutputsavedeventpayload.md | 24 +++ .../data-types/secretaddedeventpayload.md | 19 ++ .../data-types/secretdeletedeventpayload.md | 19 ++ ...load.md => serverrequestedeventpayload.md} | 6 +- ...d.md => serverstatechangedeventpayload.md} | 6 +- ...ntpayload.md => vmassignedeventpayload.md} | 6 +- .../vmgamecertificatesdeployedeventpayload.md | 22 ++ ....md => vmremoteusercreatedeventpayload.md} | 6 +- ....md => vmremoteuserdeletedeventpayload.md} | 6 +- .../data-types/vmstatechangeeventpayload.md | 23 ++ ...d => vmunassignmentstartedeventpayload.md} | 6 +- ...tpayload.md => vmunhealthyeventpayload.md} | 6 +- .../events/enabled-for-title.md | 43 ++++ ...asset-deleted.md => game-asset-deleted.md} | 9 +- playfab-docs/api-references/events/index.md | 101 ++++++--- .../events/monitoring-output-saved.md | 44 ++++ .../api-references/events/secret-added.md | 44 ++++ .../api-references/events/secret-deleted.md | 44 ++++ ...r-build-deleted.md => server-requested.md} | 10 +- ...ate-changed.md => server-state-changed.md} | 8 +- ...r-server-vm-assigned.md => vm-assigned.md} | 8 +- .../events/vm-game-certificates-deployed.md | 44 ++++ ...r-created.md => vm-remote-user-created.md} | 8 +- ...r-deleted.md => vm-remote-user-deleted.md} | 8 +- .../api-references/events/vm-state-change.md | 44 ++++ ...-started.md => vm-unassignment-started.md} | 9 +- ...server-vm-unhealthy.md => vm-unhealthy.md} | 9 +- playfab-docs/api-references/toc.yml | 74 ++++--- playfab-docs/identity/index.yml | 2 + .../platform-specific-authentication/index.md | 1 + .../xbox-add-on/Xbox-live-add-on-page.png | Bin 0 -> 233811 bytes .../partner-center-configuration-page.png | Bin 0 -> 42454 bytes .../xbox-add-on/partner-center-product-id.png | Bin 0 -> 104525 bytes .../xbox-add-on-installation-validation.png | Bin 0 -> 59662 bytes .../xbox-add-on/xbox-add-on-installation.png | Bin 0 -> 71899 bytes .../platform-specific-authentication/toc.yml | 2 + .../xbox-live-add-on.md | 64 ++++++ .../available-built-in-entity-types.md | 2 +- .../multiplayer/networking/release-notes.md | 21 ++ .../game-saves/conflicts.md | 202 ++++++++++++++++-- 66 files changed, 1218 insertions(+), 179 deletions(-) create mode 100644 playfab-docs/api-references/events/build-alias-created.md create mode 100644 playfab-docs/api-references/events/build-alias-deleted.md create mode 100644 playfab-docs/api-references/events/build-alias-updated.md rename playfab-docs/api-references/events/{multiplayer-server-requested.md => build-deleted.md} (90%) rename playfab-docs/api-references/events/{multiplayer-server-build-region-status-changed.md => build-region-status-changed.md} (87%) rename playfab-docs/api-references/events/{multiplayer-server-build-region-updated.md => build-region-updated.md} (89%) create mode 100644 playfab-docs/api-references/events/build-region-utilization.md rename playfab-docs/api-references/events/{multiplayer-server-certificate-deleted.md => certificate-deleted.md} (89%) rename playfab-docs/api-references/events/{multiplayer-server-certificate-uploaded.md => certificate-uploaded.md} (89%) create mode 100644 playfab-docs/api-references/events/crash-detected.md rename playfab-docs/api-references/events/{multiplayer-server-create-build-initiated.md => create-build-initiated.md} (88%) create mode 100644 playfab-docs/api-references/events/data-types/buildaliascreatedeventpayload.md create mode 100644 playfab-docs/api-references/events/data-types/buildaliasdeletedeventpayload.md create mode 100644 playfab-docs/api-references/events/data-types/buildaliasupdatedeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerserverbuilddeletedeventpayload.md => builddeletedeventpayload.md} (70%) rename playfab-docs/api-references/events/data-types/{multiplayerserverbuildregionstatuschangedeventpayload.md => buildregionstatuschangedeventpayload.md} (74%) rename playfab-docs/api-references/events/data-types/{multiplayerserverbuildregionupdatedeventpayload.md => buildregionupdatedeventpayload.md} (74%) create mode 100644 playfab-docs/api-references/events/data-types/buildregionutilizationeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerservercertificatedeletedeventpayload.md => certificatedeletedeventpayload.md} (67%) rename playfab-docs/api-references/events/data-types/{multiplayerservercertificateuploadedeventpayload.md => certificateuploadedeventpayload.md} (66%) create mode 100644 playfab-docs/api-references/events/data-types/crashdetectedeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerservercreatebuildinitiatedeventpayload.md => createbuildinitiatedeventpayload.md} (73%) rename playfab-docs/api-references/events/data-types/{multiplayerservergameassetdeletedeventpayload.md => gameassetdeletedeventpayload.md} (67%) create mode 100644 playfab-docs/api-references/events/data-types/gamecertificatedeployed.md create mode 100644 playfab-docs/api-references/events/data-types/monitoringoutputsavedeventpayload.md create mode 100644 playfab-docs/api-references/events/data-types/secretaddedeventpayload.md create mode 100644 playfab-docs/api-references/events/data-types/secretdeletedeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerserverrequestedeventpayload.md => serverrequestedeventpayload.md} (86%) rename playfab-docs/api-references/events/data-types/{multiplayerserverstatechangedeventpayload.md => serverstatechangedeventpayload.md} (80%) rename playfab-docs/api-references/events/data-types/{multiplayerservervmassignedeventpayload.md => vmassignedeventpayload.md} (81%) create mode 100644 playfab-docs/api-references/events/data-types/vmgamecertificatesdeployedeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerservervmremoteusercreatedeventpayload.md => vmremoteusercreatedeventpayload.md} (74%) rename playfab-docs/api-references/events/data-types/{multiplayerservervmremoteuserdeletedeventpayload.md => vmremoteuserdeletedeventpayload.md} (76%) create mode 100644 playfab-docs/api-references/events/data-types/vmstatechangeeventpayload.md rename playfab-docs/api-references/events/data-types/{multiplayerservervmunassignmentstartedeventpayload.md => vmunassignmentstartedeventpayload.md} (81%) rename playfab-docs/api-references/events/data-types/{multiplayerservervmunhealthyeventpayload.md => vmunhealthyeventpayload.md} (76%) create mode 100644 playfab-docs/api-references/events/enabled-for-title.md rename playfab-docs/api-references/events/{multiplayer-server-game-asset-deleted.md => game-asset-deleted.md} (89%) create mode 100644 playfab-docs/api-references/events/monitoring-output-saved.md create mode 100644 playfab-docs/api-references/events/secret-added.md create mode 100644 playfab-docs/api-references/events/secret-deleted.md rename playfab-docs/api-references/events/{multiplayer-server-build-deleted.md => server-requested.md} (87%) rename playfab-docs/api-references/events/{multiplayer-server-state-changed.md => server-state-changed.md} (90%) rename playfab-docs/api-references/events/{multiplayer-server-vm-assigned.md => vm-assigned.md} (90%) create mode 100644 playfab-docs/api-references/events/vm-game-certificates-deployed.md rename playfab-docs/api-references/events/{multiplayer-server-vm-remote-user-created.md => vm-remote-user-created.md} (88%) rename playfab-docs/api-references/events/{multiplayer-server-vm-remote-user-deleted.md => vm-remote-user-deleted.md} (88%) create mode 100644 playfab-docs/api-references/events/vm-state-change.md rename playfab-docs/api-references/events/{multiplayer-server-vm-unassignment-started.md => vm-unassignment-started.md} (88%) rename playfab-docs/api-references/events/{multiplayer-server-vm-unhealthy.md => vm-unhealthy.md} (89%) create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/Xbox-live-add-on-page.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/partner-center-configuration-page.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/partner-center-product-id.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/xbox-add-on-installation-validation.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/xbox-add-on-installation.png create mode 100644 playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md diff --git a/.acrolinx-config.edn b/.acrolinx-config.edn index cddebf863..fd2404316 100644 --- a/.acrolinx-config.edn +++ b/.acrolinx-config.edn @@ -11,7 +11,7 @@ } :scores { ;;:terminology 100 - :qualityscore 70 + :qualityscore 80 ;;:spelling 40 } } diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6b7393165..f13af9242 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,4 +5,4 @@ # The '*' pattern is global owners. -/playfab-docs/ @KevinAsgari @williacj @thomasgu +/playfab-docs/ @MicrosoftDocs/xbox-learning-resources @williacj @thomasgu diff --git a/playfab-docs/api-references/events/build-alias-created.md b/playfab-docs/api-references/events/build-alias-created.md new file mode 100644 index 000000000..4b1c0ab8d --- /dev/null +++ b/playfab-docs/api-references/events/build-alias-created.md @@ -0,0 +1,44 @@ +--- +title: build_alias_created +author: valexao +description: build_alias_created event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# build_alias_created + +This event is triggered when a multiplayer server build alias is created. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[BuildAliasCreatedEventPayload](data-types/buildaliascreatedeventpayload.md)|The multiplayer server build alias created event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/build-alias-deleted.md b/playfab-docs/api-references/events/build-alias-deleted.md new file mode 100644 index 000000000..5a96b8b54 --- /dev/null +++ b/playfab-docs/api-references/events/build-alias-deleted.md @@ -0,0 +1,43 @@ +--- +title: build_alias_deleted +author: valexao +description: build_alias_deleted event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# build_alias_deleted + +This event is triggered when a multiplayer server build alias is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[BuildAliasDeletedEventPayload](data-types/buildaliasdeletedeventpayload.md)|The multiplayer server build alias deleted event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| diff --git a/playfab-docs/api-references/events/build-alias-updated.md b/playfab-docs/api-references/events/build-alias-updated.md new file mode 100644 index 000000000..ae3275574 --- /dev/null +++ b/playfab-docs/api-references/events/build-alias-updated.md @@ -0,0 +1,44 @@ +--- +title: build_alias_updated +author: valexao +description: build_alias_updated event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# build_alias_updated + +This event is triggered when a multiplayer server build alias is updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[BuildAliasUpdatedEventPayload](data-types/buildaliasupdatedeventpayload.md)|The multiplayer server build alias updated event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-requested.md b/playfab-docs/api-references/events/build-deleted.md similarity index 90% rename from playfab-docs/api-references/events/multiplayer-server-requested.md rename to playfab-docs/api-references/events/build-deleted.md index 30a437724..1a1ede519 100644 --- a/playfab-docs/api-references/events/multiplayer-server-requested.md +++ b/playfab-docs/api-references/events/build-deleted.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_requested +title: build_deleted author: joannaleecy -description: multiplayer_server_requested event. +description: build_deleted event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,9 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_requested +# build_deleted + +This event is triggered when a multiplayer server build is deleted. ## Properties @@ -19,7 +21,7 @@ ms.localizationpriority: medium |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerRequestedEventPayload](data-types/multiplayerserverrequestedeventpayload.md)|The multiplayer server requested event payload.| +|Payload|[BuildDeletedEventPayload](data-types/builddeletedeventpayload.md)|The multiplayer server build deleted event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-build-region-status-changed.md b/playfab-docs/api-references/events/build-region-status-changed.md similarity index 87% rename from playfab-docs/api-references/events/multiplayer-server-build-region-status-changed.md rename to playfab-docs/api-references/events/build-region-status-changed.md index ece9c11ce..55c945293 100644 --- a/playfab-docs/api-references/events/multiplayer-server-build-region-status-changed.md +++ b/playfab-docs/api-references/events/build-region-status-changed.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_build_region_status_changed +title: build_region_status_changed author: joannaleecy -description: multiplayer_server_build_region_status_changed event. +description: build_region_status_changed event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_build_region_status_changed +# build_region_status_changed This event is triggered when a multiplayer server's build region status is changed. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server's build region status is chang |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerBuildRegionStatusChangedEventPayload](data-types/multiplayerserverbuildregionstatuschangedeventpayload.md)|The multiplayer server build region status changed event payload.| +|Payload|[BuildRegionStatusChangedEventPayload](data-types/buildregionstatuschangedeventpayload.md)|The multiplayer server build region status changed event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-build-region-updated.md b/playfab-docs/api-references/events/build-region-updated.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-build-region-updated.md rename to playfab-docs/api-references/events/build-region-updated.md index 049fc51ec..56dbe2c75 100644 --- a/playfab-docs/api-references/events/multiplayer-server-build-region-updated.md +++ b/playfab-docs/api-references/events/build-region-updated.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_build_region_updated +title: build_region_updated author: joannaleecy -description: multiplayer_server_build_region_updated event. +description: build_region_updated event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_build_region_updated +# build_region_updated This event is triggered when a multiplayer server build region is updated. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server build region is updated. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerBuildRegionUpdatedEventPayload](data-types/multiplayerserverbuildregionupdatedeventpayload.md)|The multiplayer server build region updated event payload.| +|Payload|[BuildRegionUpdatedEventPayload](data-types/buildregionupdatedeventpayload.md)|The multiplayer server build region updated event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/build-region-utilization.md b/playfab-docs/api-references/events/build-region-utilization.md new file mode 100644 index 000000000..2c71f7e1e --- /dev/null +++ b/playfab-docs/api-references/events/build-region-utilization.md @@ -0,0 +1,44 @@ +--- +title: build_region_utilization +author: valexao +description: build_region_utilization event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# build_region_utilization + +This event is triggered to display the utilization of servers for a build in each region. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[BuildRegionUtilizationEventPayload](data-types/buildregionutilizationeventpayload.md)|The multiplayer server build region utilization event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-certificate-deleted.md b/playfab-docs/api-references/events/certificate-deleted.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-certificate-deleted.md rename to playfab-docs/api-references/events/certificate-deleted.md index 3c3b36856..421b229df 100644 --- a/playfab-docs/api-references/events/multiplayer-server-certificate-deleted.md +++ b/playfab-docs/api-references/events/certificate-deleted.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_certificate_deleted +title: certificate_deleted author: joannaleecy -description: multiplayer_server_certificate_deleted event. +description: certificate_deleted event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_certificate_deleted +# certificate_deleted This event is triggered when a multiplayer server certificate is deleted. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server certificate is deleted. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerCertificateDeletedEventPayload](data-types/multiplayerservercertificatedeletedeventpayload.md)|The multiplayer server certificate deleted event payload.| +|Payload|[CertificateDeletedEventPayload](data-types/certificatedeletedeventpayload.md)|The multiplayer server certificate deleted event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-certificate-uploaded.md b/playfab-docs/api-references/events/certificate-uploaded.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-certificate-uploaded.md rename to playfab-docs/api-references/events/certificate-uploaded.md index f7a797151..d54bc860a 100644 --- a/playfab-docs/api-references/events/multiplayer-server-certificate-uploaded.md +++ b/playfab-docs/api-references/events/certificate-uploaded.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_certificate_uploaded +title: certificate_uploaded author: joannaleecy -description: multiplayer_server_certificate_uploaded event. +description: certificate_uploaded event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_certificate_uploaded +# certificate_uploaded This event is triggered when a multiplayer server certificate is uploaded. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server certificate is uploaded. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerCertificateUploadedEventPayload](data-types/multiplayerservercertificateuploadedeventpayload.md)|The multiplayer server certificate uploaded event payload.| +|Payload|[CertificateUploadedEventPayload](data-types/certificateuploadedeventpayload.md)|The multiplayer server certificate uploaded event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/crash-detected.md b/playfab-docs/api-references/events/crash-detected.md new file mode 100644 index 000000000..dddec0188 --- /dev/null +++ b/playfab-docs/api-references/events/crash-detected.md @@ -0,0 +1,44 @@ +--- +title: crash_detected +author: valexao +description: crash_detected event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# crash_detected + +This event triggered when a crash dump is found on a terminating server. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[CrashDetectedEventPayload](data-types/crashdetectedeventpayload.md)|The multiplayer server crash detected event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-create-build-initiated.md b/playfab-docs/api-references/events/create-build-initiated.md similarity index 88% rename from playfab-docs/api-references/events/multiplayer-server-create-build-initiated.md rename to playfab-docs/api-references/events/create-build-initiated.md index c0065eeda..92253f0d0 100644 --- a/playfab-docs/api-references/events/multiplayer-server-create-build-initiated.md +++ b/playfab-docs/api-references/events/create-build-initiated.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_create_build_initiated +title: create_build_initiated author: joannaleecy -description: multiplayer_server_create_build_initiated event. +description: create_build_initiated event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_create_build_initiated +# create_build_initiated This event is triggered when a multiplayer server build is initiated. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server build is initiated. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerCreateBuildInitiatedEventPayload](data-types/multiplayerservercreatebuildinitiatedeventpayload.md)|The multiplayer server create build initiated event payload.| +|Payload|[CreateBuildInitiatedEventPayload](data-types/createbuildinitiatedeventpayload.md)|The multiplayer server create build initiated event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/data-types/buildaliascreatedeventpayload.md b/playfab-docs/api-references/events/data-types/buildaliascreatedeventpayload.md new file mode 100644 index 000000000..c6cb27d95 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/buildaliascreatedeventpayload.md @@ -0,0 +1,20 @@ +--- +title: BuildAliasCreatedEventPayload +author: valexao +description: BuildAliasCreatedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# BuildAliasCreatedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|AliasName|String|The name of the build alias that was created.| +|AliasId|String|The Guid ID of the build alias that was created.| diff --git a/playfab-docs/api-references/events/data-types/buildaliasdeletedeventpayload.md b/playfab-docs/api-references/events/data-types/buildaliasdeletedeventpayload.md new file mode 100644 index 000000000..a585f18ff --- /dev/null +++ b/playfab-docs/api-references/events/data-types/buildaliasdeletedeventpayload.md @@ -0,0 +1,19 @@ +--- +title: BuildAliasDeletedEventPayload +author: valexao +description: BuildAliasDeletedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# BuildAliasDeletedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|AliasId|String|The Guid ID of the build alias that was deleted.| diff --git a/playfab-docs/api-references/events/data-types/buildaliasupdatedeventpayload.md b/playfab-docs/api-references/events/data-types/buildaliasupdatedeventpayload.md new file mode 100644 index 000000000..67c1eab2e --- /dev/null +++ b/playfab-docs/api-references/events/data-types/buildaliasupdatedeventpayload.md @@ -0,0 +1,20 @@ +--- +title: BuildAliasUpdatedEventPayload +author: valexao +description: BuildAliasUpdatedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# BuildAliasUpdatedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|AliasName|String|The name of the build alias that was updated.| +|AliasId|String|The Guid ID of the build alias that was updated.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverbuilddeletedeventpayload.md b/playfab-docs/api-references/events/data-types/builddeletedeventpayload.md similarity index 70% rename from playfab-docs/api-references/events/data-types/multiplayerserverbuilddeletedeventpayload.md rename to playfab-docs/api-references/events/data-types/builddeletedeventpayload.md index 264ec7491..50343df28 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverbuilddeletedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/builddeletedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerBuildDeletedEventPayload +title: BuildDeletedEventPayload author: joannaleecy -description: MultiplayerServerBuildDeletedEventPayload data type. +description: BuildDeletedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerBuildDeletedEventPayload +# BuildDeletedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverbuildregionstatuschangedeventpayload.md b/playfab-docs/api-references/events/data-types/buildregionstatuschangedeventpayload.md similarity index 74% rename from playfab-docs/api-references/events/data-types/multiplayerserverbuildregionstatuschangedeventpayload.md rename to playfab-docs/api-references/events/data-types/buildregionstatuschangedeventpayload.md index 58c5bf085..d55fae1eb 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverbuildregionstatuschangedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/buildregionstatuschangedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerBuildRegionStatusChangedEventPayload +title: BuildRegionStatusChangedEventPayload author: joannaleecy -description: MultiplayerServerBuildRegionStatusChangedEventPayload data type. +description: BuildRegionStatusChangedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerBuildRegionStatusChangedEventPayload +# BuildRegionStatusChangedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverbuildregionupdatedeventpayload.md b/playfab-docs/api-references/events/data-types/buildregionupdatedeventpayload.md similarity index 74% rename from playfab-docs/api-references/events/data-types/multiplayerserverbuildregionupdatedeventpayload.md rename to playfab-docs/api-references/events/data-types/buildregionupdatedeventpayload.md index 46c25e274..49533b362 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverbuildregionupdatedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/buildregionupdatedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerBuildRegionUpdatedEventPayload +title: BuildRegionUpdatedEventPayload author: joannaleecy -description: MultiplayerServerBuildRegionUpdatedEventPayload data type. +description: BuildRegionUpdatedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerBuildRegionUpdatedEventPayload +# BuildRegionUpdatedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/buildregionutilizationeventpayload.md b/playfab-docs/api-references/events/data-types/buildregionutilizationeventpayload.md new file mode 100644 index 000000000..f59a30494 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/buildregionutilizationeventpayload.md @@ -0,0 +1,25 @@ +--- +title: BuildRegionUtilizationEventPayload +author: valexao +description: BuildRegionUtilizationEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# BuildRegionUtilizationEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The guid string ID of the multiplayer server build that regions were updated on.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|Active|Int|The number of active servers.| +|StandingBy|Int|The number of standingby servers.| +|Propping|Int|The number of servers still downloading game resources.| +|Total|Int|The total number of servers.| +|VmCount|Int|The total number of running virtual machines.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerservercertificatedeletedeventpayload.md b/playfab-docs/api-references/events/data-types/certificatedeletedeventpayload.md similarity index 67% rename from playfab-docs/api-references/events/data-types/multiplayerservercertificatedeletedeventpayload.md rename to playfab-docs/api-references/events/data-types/certificatedeletedeventpayload.md index 0de591ca1..a6c2fd2db 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservercertificatedeletedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/certificatedeletedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerCertificateDeletedEventPayload +title: CertificateDeletedEventPayload author: joannaleecy -description: MultiplayerServerCertificateDeletedEventPayload data type. +description: CertificateDeletedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerCertificateDeletedEventPayload +# CertificateDeletedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservercertificateuploadedeventpayload.md b/playfab-docs/api-references/events/data-types/certificateuploadedeventpayload.md similarity index 66% rename from playfab-docs/api-references/events/data-types/multiplayerservercertificateuploadedeventpayload.md rename to playfab-docs/api-references/events/data-types/certificateuploadedeventpayload.md index e85c07fac..cd663316e 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservercertificateuploadedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/certificateuploadedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MMultiplayerServerCertificateUploadedEventPayload +title: CertificateUploadedEventPayload author: joannaleecy -description: MultiplayerServerCertificateUploadedEventPayload data type. +description: CertificateUploadedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerCertificateUploadedEventPayload +# CertificateUploadedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/crashdetectedeventpayload.md b/playfab-docs/api-references/events/data-types/crashdetectedeventpayload.md new file mode 100644 index 000000000..38ce9d734 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/crashdetectedeventpayload.md @@ -0,0 +1,24 @@ +--- +title: CrashDetectedEventPayload +author: valexao +description: CrashDetectedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# CrashDetectedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The guid string ID of the multiplayer server build that regions were updated on.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|ServerId|String|The guid string ID of the session.| +|VmId|String|The virtual machine ID the multiplayer server is located on.| +|CrashDumpUploaded|bool|If true, the crash dump was uploaded with the server's logs.| +|CrashDumpStatus|String|The reason a crash dump wasn't uploaded. If null, assume no crash dump was found.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerservercreatebuildinitiatedeventpayload.md b/playfab-docs/api-references/events/data-types/createbuildinitiatedeventpayload.md similarity index 73% rename from playfab-docs/api-references/events/data-types/multiplayerservercreatebuildinitiatedeventpayload.md rename to playfab-docs/api-references/events/data-types/createbuildinitiatedeventpayload.md index 0a3b999be..d4827582c 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservercreatebuildinitiatedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/createbuildinitiatedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerCreateBuildInitiatedEventPayload +title: CreateBuildInitiatedEventPayload author: joannaleecy -description: MultiplayerServerCreateBuildInitiatedEventPayload data type. +description: CreateBuildInitiatedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerCreateBuildInitiatedEventPayload +# CreateBuildInitiatedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservergameassetdeletedeventpayload.md b/playfab-docs/api-references/events/data-types/gameassetdeletedeventpayload.md similarity index 67% rename from playfab-docs/api-references/events/data-types/multiplayerservergameassetdeletedeventpayload.md rename to playfab-docs/api-references/events/data-types/gameassetdeletedeventpayload.md index 3c90072f2..12cdf018b 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservergameassetdeletedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/gameassetdeletedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerGameAssetDeletedEventPayload +title: GameAssetDeletedEventPayload author: joannaleecy -description: MMultiplayerServerGameAssetDeletedEventPayload data type. +description: GameAssetDeletedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerGameAssetDeletedEventPayload +# GameAssetDeletedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/gamecertificatedeployed.md b/playfab-docs/api-references/events/data-types/gamecertificatedeployed.md new file mode 100644 index 000000000..c5356515f --- /dev/null +++ b/playfab-docs/api-references/events/data-types/gamecertificatedeployed.md @@ -0,0 +1,24 @@ +--- +title: GameCertificateDeployed +author: valexao +description: GameCertificateDeployed data type. +ms.author: vorelien +ms.date: 12/10/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# GameCertificateDeployed + +Information about the game certificate deployed in the VM. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Name|String|The certificate name.| +|Thumbprint|String|The certificate thumbprint.| +|Version|String|The certificate version.| +|Expiration|String|The certificate expiration date.| diff --git a/playfab-docs/api-references/events/data-types/monitoringoutputsavedeventpayload.md b/playfab-docs/api-references/events/data-types/monitoringoutputsavedeventpayload.md new file mode 100644 index 000000000..08c74dc0c --- /dev/null +++ b/playfab-docs/api-references/events/data-types/monitoringoutputsavedeventpayload.md @@ -0,0 +1,24 @@ +--- +title: MonitoringOutputSavedEventPayload +author: valexao +description: MonitoringOutputSavedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# MonitoringOutputSavedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The Guid string ID of the build.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|ServerId|String|The multiplayer server ID.| +|SessionId|String|The Guid string ID of the session.| +|VmId|String|The virtual machine ID the multiplayer server is located on.| +|IsVmLevel|bool|True if the monitoring output was not associated with a running server.| diff --git a/playfab-docs/api-references/events/data-types/secretaddedeventpayload.md b/playfab-docs/api-references/events/data-types/secretaddedeventpayload.md new file mode 100644 index 000000000..07c3fa7c3 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/secretaddedeventpayload.md @@ -0,0 +1,19 @@ +--- +title: SecretAddedEventPayload +author: valexao +description: SecretAddedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# SecretAddedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|SecretName|String|The name of the secret that was added.| diff --git a/playfab-docs/api-references/events/data-types/secretdeletedeventpayload.md b/playfab-docs/api-references/events/data-types/secretdeletedeventpayload.md new file mode 100644 index 000000000..83aa53d1a --- /dev/null +++ b/playfab-docs/api-references/events/data-types/secretdeletedeventpayload.md @@ -0,0 +1,19 @@ +--- +title: SecretDeletedEventPayload +author: valexao +description: SecretDeletedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# SecretDeletedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|SecretName|String|The name of the secret that was deleted.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverrequestedeventpayload.md b/playfab-docs/api-references/events/data-types/serverrequestedeventpayload.md similarity index 86% rename from playfab-docs/api-references/events/data-types/multiplayerserverrequestedeventpayload.md rename to playfab-docs/api-references/events/data-types/serverrequestedeventpayload.md index d0fbbf6d0..d710af185 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverrequestedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/serverrequestedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerRequestedEventPayload +title: ServerRequestedEventPayload author: joannaleecy -description: MultiplayerServerRequestedEventPayload data type. +description: ServerRequestedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerRequestedEventPayload +# ServerRequestedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerserverstatechangedeventpayload.md b/playfab-docs/api-references/events/data-types/serverstatechangedeventpayload.md similarity index 80% rename from playfab-docs/api-references/events/data-types/multiplayerserverstatechangedeventpayload.md rename to playfab-docs/api-references/events/data-types/serverstatechangedeventpayload.md index ff1961a84..82840961c 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerserverstatechangedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/serverstatechangedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerStateChangedEventPayload +title: ServerStateChangedEventPayload author: joannaleecy -description: MultiplayerServerStateChangedEventPayload data type. +description: ServerStateChangedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerStateChangedEventPayload +# ServerStateChangedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmassignedeventpayload.md b/playfab-docs/api-references/events/data-types/vmassignedeventpayload.md similarity index 81% rename from playfab-docs/api-references/events/data-types/multiplayerservervmassignedeventpayload.md rename to playfab-docs/api-references/events/data-types/vmassignedeventpayload.md index 051ec25a4..71ed8541c 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmassignedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmassignedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmAssignedEventPayload +title: VmAssignedEventPayload author: joannaleecy -description: MultiplayerServerVmAssignedEventPayload data type. +description: VmAssignedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmAssignedEventPayload +# VmAssignedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/vmgamecertificatesdeployedeventpayload.md b/playfab-docs/api-references/events/data-types/vmgamecertificatesdeployedeventpayload.md new file mode 100644 index 000000000..bf2559090 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/vmgamecertificatesdeployedeventpayload.md @@ -0,0 +1,22 @@ +--- +title: VmGameCertificatesDeployedEventPayload +author: valexao +description: VmGameCertificatesDeployedEventPayload data type. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# VmGameCertificatesDeployedEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The GUID string ID of the build.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|VmId|String|The ID of the virtual machine that was assigned.| +|GameCertificates|[List\](gamecertificatedeployed.md)|The list of game certificates deployed.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmremoteusercreatedeventpayload.md b/playfab-docs/api-references/events/data-types/vmremoteusercreatedeventpayload.md similarity index 74% rename from playfab-docs/api-references/events/data-types/multiplayerservervmremoteusercreatedeventpayload.md rename to playfab-docs/api-references/events/data-types/vmremoteusercreatedeventpayload.md index 1b8cfcaad..e8b5f7a32 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmremoteusercreatedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmremoteusercreatedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmRemoteUserCreatedEventPayload +title: VmRemoteUserCreatedEventPayload author: joannaleecy -description: MultiplayerServerVmRemoteUserCreatedEventPayload data type. +description: VmRemoteUserCreatedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmRemoteUserCreatedEventPayload +# VmRemoteUserCreatedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmremoteuserdeletedeventpayload.md b/playfab-docs/api-references/events/data-types/vmremoteuserdeletedeventpayload.md similarity index 76% rename from playfab-docs/api-references/events/data-types/multiplayerservervmremoteuserdeletedeventpayload.md rename to playfab-docs/api-references/events/data-types/vmremoteuserdeletedeventpayload.md index 23f32a80a..8f32e251a 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmremoteuserdeletedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmremoteuserdeletedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmRemoteUserDeletedEventPayload +title: VmRemoteUserDeletedEventPayload author: joannaleecy -description: MultiplayerServerVmRemoteUserDeletedEventPayload data type. +description: VmRemoteUserDeletedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmRemoteUserDeletedEventPayload +# VmRemoteUserDeletedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/vmstatechangeeventpayload.md b/playfab-docs/api-references/events/data-types/vmstatechangeeventpayload.md new file mode 100644 index 000000000..76a303e7a --- /dev/null +++ b/playfab-docs/api-references/events/data-types/vmstatechangeeventpayload.md @@ -0,0 +1,23 @@ +--- +title: VmStateChangeEventPayload +author: valexao +description: VmStateChangeEventPayload data type. +ms.author: vorelien +ms.date: 12/10/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# VmStateChangeEventPayload + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|BuildId|String|The guid string ID of the multiplayer server build that regions were updated on.| +|Region|[AzureRegion](azureregion.md)|The build region.| +|VmId|String|The virtual machine ID of the multiplayer vm.| +|State|String|The multiplayer virtual machine's state to report on.| +|DurationSeconds|ulong|The amount of time spent getting to this state.| diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmunassignmentstartedeventpayload.md b/playfab-docs/api-references/events/data-types/vmunassignmentstartedeventpayload.md similarity index 81% rename from playfab-docs/api-references/events/data-types/multiplayerservervmunassignmentstartedeventpayload.md rename to playfab-docs/api-references/events/data-types/vmunassignmentstartedeventpayload.md index bc7181532..4c6ebc46e 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmunassignmentstartedeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmunassignmentstartedeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmUnassignmentStartedEventPayload +title: VmUnassignmentStartedEventPayload author: joannaleecy -description: MultiplayerServerVmUnassignmentStartedEventPayload data type. +description: VmUnassignmentStartedEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmUnassignmentStartedEventPayload +# VmUnassignmentStartedEventPayload ## Properties diff --git a/playfab-docs/api-references/events/data-types/multiplayerservervmunhealthyeventpayload.md b/playfab-docs/api-references/events/data-types/vmunhealthyeventpayload.md similarity index 76% rename from playfab-docs/api-references/events/data-types/multiplayerservervmunhealthyeventpayload.md rename to playfab-docs/api-references/events/data-types/vmunhealthyeventpayload.md index a02a85421..c0c3f5898 100644 --- a/playfab-docs/api-references/events/data-types/multiplayerservervmunhealthyeventpayload.md +++ b/playfab-docs/api-references/events/data-types/vmunhealthyeventpayload.md @@ -1,7 +1,7 @@ --- -title: MultiplayerServerVmUnhealthyEventPayload +title: VmUnhealthyEventPayload author: joannaleecy -description: MultiplayerServerVmUnhealthyEventPayload data type. +description: VmUnhealthyEventPayload data type. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# MultiplayerServerVmUnhealthyEventPayload +# VmUnhealthyEventPayload ## Properties diff --git a/playfab-docs/api-references/events/enabled-for-title.md b/playfab-docs/api-references/events/enabled-for-title.md new file mode 100644 index 000000000..55b2b7094 --- /dev/null +++ b/playfab-docs/api-references/events/enabled-for-title.md @@ -0,0 +1,43 @@ +--- +title: enabled_for_title +author: valexao +description: enabled_for_title event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# enabled_for_title + +This event is triggered when a title enables PlayFab multiplayer servers. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-game-asset-deleted.md b/playfab-docs/api-references/events/game-asset-deleted.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-game-asset-deleted.md rename to playfab-docs/api-references/events/game-asset-deleted.md index dcbbecbdd..f966cb5b4 100644 --- a/playfab-docs/api-references/events/multiplayer-server-game-asset-deleted.md +++ b/playfab-docs/api-references/events/game-asset-deleted.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_game_asset_deleted +title: game_asset_deleted author: joannaleecy -description: multiplayer_server_game_asset_deleted event. +description: game_asset_deleted event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,8 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_game_asset_deleted - +# game_asset_deleted This event is triggered when a multiplayer server game asset is deleted. ## Properties @@ -21,7 +20,7 @@ This event is triggered when a multiplayer server game asset is deleted. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerGameAssetDeletedEventPayload](data-types/multiplayerservergameassetdeletedeventpayload.md)|The multiplayer server game asset deleted event payload.| +|Payload|[GameAssetDeletedEventPayload](data-types/gameassetdeletedeventpayload.md)|The multiplayer server game asset deleted event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 95c293b53..4b6c1d4d7 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -81,66 +81,101 @@ Each event type has a set of properties that are included as part of event's dat - [matchmaking_user_ticket_invite](matchmaking-user-ticket-invite.md) This event is triggered when a ticket with an invited user is created. The event will be sent to the invited user. -- [multiplayer_server_build_deleted](multiplayer-server-build-deleted.md) +- [studio_created](studio-created.md) + This event is triggered when a studio is created. + +- [studio_user_added](studio-user-added.md) + This event is triggered when a user accepts a studio invitation. + +- [studio_user_invited](studio-user-invited.md) + This event is triggered when a user is invited to a studio. + +- [studio_user_removed](studio-user-removed.md) + This event is triggered when a user is removed from a studio. + +- [tenancy_connector_onboard](tenancy-connector-onboard.md) + This event is triggered when a tenancy connector is onboarded. + +- [studio_tier_updated](studio-tier-updated.md) + This event is triggered when a studio tier is updated. + +## Multiplayer Servers + +- [build_alias_created](build-alias-created.md) + This event is triggered when a multiplayer server build alias is created. + +- [build_alias_deleted](build-alias-deleted.md) + This event is triggered when a multiplayer server build alias is deleted. + +- [build_alias_updated](build-alias-updated.md) + This event is triggered when a multiplayer server build alias is updated. + +- [build_deleted](build-deleted.md) This event is triggered when a multiplayer server build is deleted. -- [multiplayer_server_build_region_status_changed](multiplayer-server-build-region-status-changed.md) +- [build_region_status_changed](build-region-status-changed.md) This event is triggered when a multiplayer server's build region status is changed. -- [multiplayer_server_build_region_updated](multiplayer-server-build-region-updated.md) +- [build_region_updated](build-region-updated.md) This event is triggered when a multiplayer server build region is updated. -- [multiplayer_server_certificate_deleted](multiplayer-server-certificate-deleted.md) +- [build_region_utilization](build-region-utilization.md) + This event is triggered to display the utilization of servers for a build in each region. + +- [certificate_deleted](certificate-deleted.md) This event is triggered when a multiplayer server certificate is deleted. -- [multiplayer_server_certificate_uploaded](multiplayer-server-certificate-uploaded.md) +- [certificate_uploaded](certificate-uploaded.md) This event is triggered when a multiplayer server certificate is uploaded. -- [multiplayer_server_create_build_initiated](multiplayer-server-create-build-initiated.md) +- [crash_detected](crash-detected.md) + This event triggered when a crash dump is found on a terminating server. + +- [create_build_initiated](create-build-initiated.md) This event is triggered when a multiplayer server build is initiated. -- [multiplayer_server_game_asset_deleted](multiplayer-server-game-asset-deleted.md) +- [enabled_for_title](enabled-for-title.md) + This event is triggered when a title enables PlayFab servers + +- [game_asset_deleted](game-asset-deleted.md) This event is triggered when a multiplayer server game asset is deleted. -- [multiplayer_server_requested](multiplayer-server-requested.md) - This event is triggered when a multiplayer server shutdown is requested. +- [monitoring_output_saved](monitoring-output-saved.md) + This event is triggered when the output of a monitoring application has been saved and can be downloaded. + +- [secret_added](secret-added.md) + This event is triggered when a multiplayer server secret is added. + +- [secret_deleted](secret-deleted.md) + This event is triggered when a multiplayer server secret is deleted. -- [multiplayer_server_state_changed](multiplayer-server-state-changed.md) +- [server_requested](server-requested.md) + This event is triggered when a multiplayer server is requested. + +- [server_state_changed](server-state-changed.md) This event is triggered when a multiplayer server's state is changed. -- [multiplayer_server_vm_assigned](multiplayer-server-vm-assigned.md) +- [vm_assigned](vm-assigned.md) This event is triggered when a virtual machine is assigned to a multiplayer server build. -- [multiplayer_server_vm_remote_user_created](multiplayer-server-vm-remote-user-created.md) +- [vm_game_certificates_deployed](vm-game-certificates-deployed.md) + This event is triggered when game certificates are deployed in a game virtual machine. + +- [vm_remote_user_created](vm-remote-user-created.md) This event is triggered when a multiplayer server virtual machine remote user is created. -- [multiplayer_server_vm_remote_user_deleted](multiplayer-server-vm-remote-user-deleted.md) +- [vm_remote_user_deleted](vm-remote-user-deleted.md) This event is triggered when a multiplayer server virtual machine remote user is deleted. -- [multiplayer_server_vm_unassignment_started](multiplayer-server-vm-unassignment-started.md) +- [vm_state_change](vm-state-change.md) + This event is triggered when a multiplayer virtual machine's state is changed. + +- [vm_unassignment_started](vm-unassignment-started.md) This event is triggered when a virtual machine is unassigned from a multiplayer server build. -- [multiplayer_server_vm_unhealthy](multiplayer-server-vm-unhealthy.md) +- [vm_unhealthy](vm-unhealthy.md) This event is triggered when a virtual machine is found to be unhealthy. -- [studio_created](studio-created.md) - This event is triggered when a studio is created. - -- [studio_user_added](studio-user-added.md) - This event is triggered when a user accepts a studio invitation. - -- [studio_user_invited](studio-user-invited.md) - This event is triggered when a user is invited to a studio. - -- [studio_user_removed](studio-user-removed.md) - This event is triggered when a user is removed from a studio. - -- [tenancy_connector_onboard](tenancy-connector-onboard.md) - This event is triggered when a tenancy connector is onboarded. - -- [studio_tier_updated](studio-tier-updated.md) - This event is triggered when a studio tier is updated. - ## Catalog - [item_created](item-created.md) diff --git a/playfab-docs/api-references/events/monitoring-output-saved.md b/playfab-docs/api-references/events/monitoring-output-saved.md new file mode 100644 index 000000000..c1ac05abc --- /dev/null +++ b/playfab-docs/api-references/events/monitoring-output-saved.md @@ -0,0 +1,44 @@ +--- +title: monitoring_output_saved +author: valexao +description: monitoring_output_saved event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# monitoring_output_saved + +This event is triggered when the output of a monitoring application has been saved and can be downloaded. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[MonitoringOutputSavedEventPayload](data-types/monitoringoutputsavedeventpayload.md)|The multiplayer server monitoring output saved event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/secret-added.md b/playfab-docs/api-references/events/secret-added.md new file mode 100644 index 000000000..5d583087f --- /dev/null +++ b/playfab-docs/api-references/events/secret-added.md @@ -0,0 +1,44 @@ +--- +title: secret_added +author: valexao +description: secret_added event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# secret_added + +This event is triggered when a multiplayer server secret is added. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[SecretAddedEventPayload](data-types/secretaddedeventpayload.md)|The multiplayer server secret added event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/secret-deleted.md b/playfab-docs/api-references/events/secret-deleted.md new file mode 100644 index 000000000..f50df6f67 --- /dev/null +++ b/playfab-docs/api-references/events/secret-deleted.md @@ -0,0 +1,44 @@ +--- +title: secret_deleted +author: valexao +description: secret_deleted event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# secret_deleted + +This event is triggered when a multiplayer server secret is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[SecretDeletedEventPayload](data-types/secretdeletedeventpayload.md)|The multiplayer server secret deleted event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-build-deleted.md b/playfab-docs/api-references/events/server-requested.md similarity index 87% rename from playfab-docs/api-references/events/multiplayer-server-build-deleted.md rename to playfab-docs/api-references/events/server-requested.md index 9871653e3..47fd0cae3 100644 --- a/playfab-docs/api-references/events/multiplayer-server-build-deleted.md +++ b/playfab-docs/api-references/events/server-requested.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_build_deleted +title: server_requested author: joannaleecy -description: multiplayer_server_build_deleted event. +description: server_requested event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_build_deleted +# server_requested -This event is triggered when a multiplayer server build is deleted. +This event is triggered when a multiplayer server is requested. ## Properties @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server build is deleted. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerBuildDeletedEventPayload](data-types/multiplayerserverbuilddeletedeventpayload.md)|The multiplayer server build region deleted event payload.| +|Payload|[ServerRequestedEventPayload](data-types/serverrequestedeventpayload.md)|The multiplayer server requested event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-state-changed.md b/playfab-docs/api-references/events/server-state-changed.md similarity index 90% rename from playfab-docs/api-references/events/multiplayer-server-state-changed.md rename to playfab-docs/api-references/events/server-state-changed.md index 5750987f8..4386c2bae 100644 --- a/playfab-docs/api-references/events/multiplayer-server-state-changed.md +++ b/playfab-docs/api-references/events/server-state-changed.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_state_changed +title: server_state_changed author: joannaleecy -description: multiplayer_server_state_changed event. +description: server_state_changed event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_state_changed +# server_state_changed This event is triggered when a multiplayer server's state is changed. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server's state is changed. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerStateChangedEventPayload](data-types/multiplayerserverstatechangedeventpayload.md)|The multiplayer server state changed event payload.| +|Payload|[ServerStateChangedEventPayload](data-types/serverstatechangedeventpayload.md)|The multiplayer server state changed event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-assigned.md b/playfab-docs/api-references/events/vm-assigned.md similarity index 90% rename from playfab-docs/api-references/events/multiplayer-server-vm-assigned.md rename to playfab-docs/api-references/events/vm-assigned.md index 7f68abd32..5a3ceedc1 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-assigned.md +++ b/playfab-docs/api-references/events/vm-assigned.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_assigned +title: vm_assigned author: joannaleecy -description: multiplayer_server_vm_assigned event. +description: vm_assigned event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_assigned +# vm_assigned This event is triggered when a virtual machine is assigned to a multiplayer server build. @@ -21,7 +21,7 @@ This event is triggered when a virtual machine is assigned to a multiplayer serv |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmAssignedEventPayload](data-types/multiplayerservervmassignedeventpayload.md)|The multiplayer server virtual machine assigned event payload.| +|Payload|[VmAssignedEventPayload](data-types/vmassignedeventpayload.md)|The multiplayer server virtual machine assigned event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/vm-game-certificates-deployed.md b/playfab-docs/api-references/events/vm-game-certificates-deployed.md new file mode 100644 index 000000000..03f799863 --- /dev/null +++ b/playfab-docs/api-references/events/vm-game-certificates-deployed.md @@ -0,0 +1,44 @@ +--- +title: vm_game_certificates_deployed +author: valexao +description: vm_game_certificates_deployed event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# vm_game_certificates_deployed + +This event is triggered when game certificates are deployed in a game virtual machine. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[VmGameCertificatesDeployedEventPayload](data-types/vmgamecertificatesdeployedeventpayload.md)|The multiplayer server vm game certificates deployed event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-remote-user-created.md b/playfab-docs/api-references/events/vm-remote-user-created.md similarity index 88% rename from playfab-docs/api-references/events/multiplayer-server-vm-remote-user-created.md rename to playfab-docs/api-references/events/vm-remote-user-created.md index 032231d44..640701d81 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-remote-user-created.md +++ b/playfab-docs/api-references/events/vm-remote-user-created.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_remote_user_created +title: vm_remote_user_created author: joannaleecy -description: multiplayer_server_vm_remote_user_created event. +description: vm_remote_user_created event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_remote_user_created +# vm_remote_user_created This event is triggered when a multiplayer server virtual machine remote user is created. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server virtual machine remote user is |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmRemoteUserCreatedEventPayload](data-types/multiplayerservervmremoteusercreatedeventpayload.md)|The multiplayer server virtual machine remote user created event payload.| +|Payload|[VmRemoteUserCreatedEventPayload](data-types/vmremoteusercreatedeventpayload.md)|The multiplayer server virtual machine remote user created event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-remote-user-deleted.md b/playfab-docs/api-references/events/vm-remote-user-deleted.md similarity index 88% rename from playfab-docs/api-references/events/multiplayer-server-vm-remote-user-deleted.md rename to playfab-docs/api-references/events/vm-remote-user-deleted.md index 7040e3064..97076ab22 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-remote-user-deleted.md +++ b/playfab-docs/api-references/events/vm-remote-user-deleted.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_remote_user_deleted +title: vm_remote_user_deleted author: joannaleecy -description: multiplayer_server_vm_remote_user_deleted event. +description: vm_remote_user_deleted event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,7 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_remote_user_deleted +# vm_remote_user_deleted This event is triggered when a multiplayer server virtual machine remote user is deleted. @@ -21,7 +21,7 @@ This event is triggered when a multiplayer server virtual machine remote user is |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmRemoteUserDeletedEventPayload](data-types/multiplayerservervmremoteuserdeletedeventpayload.md)|The multiplayer server virtual machine remote user deleted event payload.| +|Payload|[VmRemoteUserDeletedEventPayload](data-types/vmremoteuserdeletedeventpayload.md)|The multiplayer server virtual machine remote user deleted event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/vm-state-change.md b/playfab-docs/api-references/events/vm-state-change.md new file mode 100644 index 000000000..049d00a4d --- /dev/null +++ b/playfab-docs/api-references/events/vm-state-change.md @@ -0,0 +1,44 @@ +--- +title: vm_state_change +author: valexao +description: vm_state_change event. +ms.author: vorelien +ms.date: 12/30/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# vm_state_change + +This event is triggered when a multiplayer virtual machine's state is changed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[VmStateChangeEventPayload](data-types/vmstatechangeeventpayload.md)|The multiplayer server vm state change event payload.| +|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| + diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-unassignment-started.md b/playfab-docs/api-references/events/vm-unassignment-started.md similarity index 88% rename from playfab-docs/api-references/events/multiplayer-server-vm-unassignment-started.md rename to playfab-docs/api-references/events/vm-unassignment-started.md index 415967b86..c51cb5bcf 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-unassignment-started.md +++ b/playfab-docs/api-references/events/vm-unassignment-started.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_unassignment_started +title: vm_unassignment_started author: joannaleecy -description: multiplayer_server_vm_unassignment_started event. +description: vm_unassignment_started event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,8 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_unassignment_started - +# vm_unassignment_started This event is triggered when a virtual machine is unassigned from a multiplayer server build. ## Properties @@ -21,7 +20,7 @@ This event is triggered when a virtual machine is unassigned from a multiplayer |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmUnassignmentStartedEventPayload](data-types/multiplayerservervmunassignmentstartedeventpayload.md)|The multiplayer server virtual machine unassignment started event payload.| +|Payload|[VmUnassignmentStartedEventPayload](data-types/vmunassignmentstartedeventpayload.md)|The multiplayer server virtual machine unassignment started event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/events/multiplayer-server-vm-unhealthy.md b/playfab-docs/api-references/events/vm-unhealthy.md similarity index 89% rename from playfab-docs/api-references/events/multiplayer-server-vm-unhealthy.md rename to playfab-docs/api-references/events/vm-unhealthy.md index 4a0244945..b1b601daa 100644 --- a/playfab-docs/api-references/events/multiplayer-server-vm-unhealthy.md +++ b/playfab-docs/api-references/events/vm-unhealthy.md @@ -1,7 +1,7 @@ --- -title: multiplayer_server_vm_unhealthy +title: vm_unhealthy author: joannaleecy -description: multiplayer_server_vm_unhealthy event. +description: vm_unhealthy event. ms.author: jenelleb ms.date: 02/19/2019 ms.topic: article @@ -10,8 +10,7 @@ keywords: playfab, playstream events ms.localizationpriority: medium --- -# multiplayer_server_vm_unhealthy - +# vm_unhealthy This event is triggered when a virtual machine is found to be unhealthy. ## Properties @@ -21,7 +20,7 @@ This event is triggered when a virtual machine is found to be unhealthy. |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[MultiplayerServerVmUnhealthyEventPayload](data-types/multiplayerservervmunhealthyeventpayload.md)|The multiplayer server virtual machine unassignment started event payload.| +|Payload|[VmUnhealthyEventPayload](data-types/vmunhealthyeventpayload.md)|The multiplayer server virtual machine unhealthy event payload.| |WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties diff --git a/playfab-docs/api-references/toc.yml b/playfab-docs/api-references/toc.yml index b1afb264f..3bad324b8 100644 --- a/playfab-docs/api-references/toc.yml +++ b/playfab-docs/api-references/toc.yml @@ -111,32 +111,54 @@ href: events/matchmaking-user-ticket-completed.md - name: matchmaking_user_ticket_invite href: events/matchmaking-user-ticket-invite.md - - name: multiplayer_server_build_deleted - href: events/multiplayer-server-build-deleted.md - - name: multiplayer_server_build_region_status_changed - href: events/multiplayer-server-build-region-status-changed.md - - name: multiplayer_server_build_region_updated - href: events/multiplayer-server-build-region-updated.md - - name: multiplayer_server_certificate_deleted - href: events/multiplayer-server-certificate-deleted.md - - name: multiplayer_server_certificate_uploaded - href: events/multiplayer-server-certificate-uploaded.md - - name: multiplayer_server_create_build_initiated - href: events/multiplayer-server-create-build-initiated.md - - name: multiplayer_server_game_asset_deleted - href: events/multiplayer-server-game-asset-deleted.md - - name: multiplayer_server_requested - href: events/multiplayer-server-requested.md - - name: multiplayer_server_state_changed - href: events/multiplayer-server-state-changed.md - - name: multiplayer_server_vm_assigned - href: events/multiplayer-server-vm-assigned.md - - name: multiplayer_server_vm_remote_user_created - href: events/multiplayer-server-vm-remote-user-created.md - - name: multiplayer_server_vm_remote_user_deleted - href: events/multiplayer-server-vm-remote-user-deleted.md - - name: multiplayer_server_vm_unassignment_started - href: events/multiplayer-server-vm-unassignment-started.md + - name: build_alias_created + href: events/build-alias-created.md + - name: build_alias_deleted + href: events/build-alias-deleted.md + - name: build_alias_updated + href: events/build-alias-updated.md + - name: build_deleted + href: events/build-deleted.md + - name: build_region_status_changed + href: events/build-region-status-changed.md + - name: build_region_updated + href: events/build-region-updated.md + - name: build_region_utilization + href: events/build-region-utilization.md + - name: certificate_deleted + href: events/certificate-deleted.md + - name: certificate_uploaded + href: events/certificate-uploaded.md + - name: crash_detected + href: events/crash-detected.md + - name: create_build_initiated + href: events/create-build-initiated.md + - name: enabled_for_title + href: events/enabled-for-title.md + - name: game_asset_deleted + href: events/game-asset-deleted.md + - name: monitoring_output_saved + href: events/monitoring-output-saved.md + - name: secret_added + href: events/secret-added.md + - name: secret_deleted + href: events/secret-deleted.md + - name: server_requested + href: events/server-requested.md + - name: server_state_changed + href: events/server-state-changed.md + - name: vm_assigned + href: events/vm-assigned.md + - name: vm_game_certificates_deployed + href: events/vm-game-certificates-deployed.md + - name: vm_remote_user_created + href: events/vm-remote-user-created.md + - name: vm_remote_user_deleted + href: events/vm-remote-user-deleted.md + - name: vm_unassignment_started + href: events/vm-unassignment-started.md + - name: vm_unhealthy + href: events/vm-unhealthy.md - name: player_action_executed href: events/player-action-executed.md - name: player_ad_activity_valued diff --git a/playfab-docs/identity/index.yml b/playfab-docs/identity/index.yml index 871e72c9f..9f390886d 100644 --- a/playfab-docs/identity/index.yml +++ b/playfab-docs/identity/index.yml @@ -52,6 +52,8 @@ landingContent: url: player-identity/platform-specific-authentication/google-sign-in-unity.md - text: Setup Sign In with Apple for PlayFab url: player-identity/platform-specific-authentication/apple-open-id.md + - text: Setting up Xbox Live title association in PlayFab + url: player-identity/platform-specific-authentication/xbox-live-add-on.md - text: Running an HTTP server for testing url: player-identity/platform-specific-authentication/running-an-http-server-for-testing.md diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/index.md b/playfab-docs/identity/player-identity/platform-specific-authentication/index.md index 1fdcb122a..a445584bc 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/index.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/index.md @@ -59,6 +59,7 @@ If you're unable to access the above secure link, see [Request access](https://a ### Windows and Xbox +- [Setting up Xbox Live title association in PlayFab](xbox-live-add-on.md) - [Authenticate Xbox Live users using PlayFab's Xbox Live Helper Library (recommended)](../../../multiplayer/networking/party-xbox-live-guide.md#mapping-between-xbox-live-user-ids-and-playfab-entity-ids) - [Setting up PlayFab authentication using Universal Windows Platform](uwp.md) - [Integrating the Universal Windows Platform with PlayFab](uwp-integration.md) diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/Xbox-live-add-on-page.png b/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/Xbox-live-add-on-page.png new file mode 100644 index 0000000000000000000000000000000000000000..602cb51922dfd4f5cc22f1b4862d664c3ed25152 GIT binary patch literal 233811 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

v?7rUU*}eV2dWp}3e>TnS{vVUU-l_iH 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

xpAF3 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 X_T^MaOTFc>*Kk8i|7zKlI}!g2j&ja^ literal 0 HcmV?d00001 diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/partner-center-configuration-page.png b/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/partner-center-configuration-page.png new file mode 100644 index 0000000000000000000000000000000000000000..d6dc1167811c17667536f13edd9181f4360e3cea GIT binary patch literal 42454 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 TbGNR$b!pY`hRw@LH;2!1ihZ~ZZ|_BzHLsc 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 literal 0 HcmV?d00001 diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/xbox-add-on-installation-validation.png b/playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/xbox-add-on-installation-validation.png new file mode 100644 index 0000000000000000000000000000000000000000..9bb590e0305d72107ed933da71029d3c0b997c4f GIT binary patch literal 59662 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 literal 0 HcmV?d00001 diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml b/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml index c5dc286b5..d5c88b4e4 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml @@ -33,6 +33,8 @@ href: uwp.md - name: Setup Sign In with Apple for PlayFab href: apple-open-id.md + - name: Setting up Xbox Live title association in PlayFab + href: xbox-live-add-on.md - name: Integrating the Universal Windows Platform with PlayFab href: uwp-integration.md - name: Setting up Playfab Authentication using Anonymous Login diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md b/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md new file mode 100644 index 000000000..596edabee --- /dev/null +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md @@ -0,0 +1,64 @@ +--- +title: Xbox Live Title Association +author: antnguyen +description: Learn how to set up and configure scoped token validation by linking Partner Center product ID to PlayFab title ID. +ms.author: antnguyen +ms.date: 10/09/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, authentication, server, partner center, xbox, xbox live +ms.localizationpriority: medium +--- + +# Setting up Xbox Live title association in PlayFab + +Learn how to configure scoped token validation by linking your Partner Center product ID to a PlayFab title ID. + +## Overview + +In this tutorial, you'll learn how to configure token validation by specifying which Xbox Live title tokens that PlayFab APIs accept when they use Xbox Live token parameters—giving you more control over integration behavior and enabling scoped token acceptance. These APIs include `Client/loginwithxbox`, `Client/LinkXboxAccount`, `Client/UnlinkXboxAccount`, `Client/ConsumeXboxEntitlement`, `Client/GetFriendLeaderboard`, `Client/GetFriendLeaderboardAroundCurrentUser`, `Client/GetFriendLeaderboardAroundPlayer`, `Client/ConsumeMicrosoftStoreEntitlements`, `Server/loginwithxbox`, `Server/LinkXboxAccount`, `Server/UnlinkXboxAccount`, `Server/GetFriendLeaderboard`, `Server/GetFriendsList`, `Server/GetFriendLeaderboardForEntity`, `Lobby/GetFriendLobbies`, `Server/GetFriendLeaderboardAroundPlayer`, `Inventory/RedeemMicrosoftStoreInventoryItems`, and `Inventory/Redeem`. + +## Requirements + +- A registered [PlayFab](https://playfab.com/) title. +- [Partner Center](https://partner.microsoft.com/) account with an Xbox Live enabled title. + +## Partner Center Product ID and Xbox Live Title ID + +Start by navigating to the product page for your Partner Center title. + +1. In the Partner Center dashboard, navigate to [Apps and Games](https://partner.microsoft.com/dashboard/apps-and-games/overview). +2. Locate and select the Xbox Live enabled Partner Center title you wish to associate with PlayFab. +3. Find and copy the Product ID from the URL of your game. + +![Parter Center product ID](media/tutorials/xbox-add-on/partner-center-product-id.png) + +4. Next find and copy the Xbox Live Title ID. Navigate to **Xbox services > Xbox Settings** and copy the **Title ID (decimal)** value. + +![Parter Center title ID](media/tutorials/xbox-add-on/partner-center-configuration-page.png) + +## Install Xbox Live Add-on + +Go to [PlayFab Game Manager](https://developer.playfab.com/) page for your title. + +1. Navigate to **Add-ons** in the menu. +2. Locate and select the **Xbox Live** Add-on icon/link. + +![Xbox live Add-on](media/tutorials/xbox-add-on/xbox-live-add-on-page.png) + +3. Use the **Seller ID** dropdown to select the correct Seller ID from Partner Center. If you don't see the correct Seller ID, select **Sign in with a different partner center account** and sign in with the correct user. + +4. Use the **Product ID** dropdown to find the Partner Center Product ID that will be linked to the PlayFab title. Confirm that the Xbox Live Title ID matches the expected Xbox Live Title ID from Partner Center. + +![PlayFab Parter Center product ID](media/tutorials/xbox-add-on/xbox-add-on-installation.png) + +5. Select **Install Xbox Network** to save the setting and restrict API calls to the selected Xbox Live Title ID. + +![Install Xbox Add-On](media/tutorials/xbox-add-on/xbox-add-on-installation-validation.png) + +By following these steps, you can confidently configure scoped Xbox Live token validation within PlayFab, ensuring that only tokens from designated Partner Center title are accepted. This setup streamlines cross-platform authentication, reinforces title-specific security, and empowers developers to deliver seamless, trusted player experiences across Xbox-enabled services. + +## Further Reading + +- [PlayFab Authentication Overview](../authentication/index.md) +- [Login Basics and Best Practices](../login/login-basics-best-practices.md) \ No newline at end of file diff --git a/playfab-docs/live-service-management/game-configuration/entities/available-built-in-entity-types.md b/playfab-docs/live-service-management/game-configuration/entities/available-built-in-entity-types.md index da010037f..ea220e468 100644 --- a/playfab-docs/live-service-management/game-configuration/entities/available-built-in-entity-types.md +++ b/playfab-docs/live-service-management/game-configuration/entities/available-built-in-entity-types.md @@ -53,7 +53,7 @@ Set the `ID` field to your game's **Title ID**. To retrieve the **Title ID**: ## master_player_account -The `master_player_account` is a player entity that is shared by all titles within your studio. +The `master_player_account` is a player entity that is shared by all titles associated to a given namespace. Set the `ID` field to the `LoginResult.PlayFabId` from the classic API. To retrieve the `LoginResult`, call one of the login methods in [Client Authentication](xref:titleid.playfabapi.com.client.authentication). diff --git a/playfab-docs/multiplayer/networking/release-notes.md b/playfab-docs/multiplayer/networking/release-notes.md index bb4ea91ce..0b48370c7 100644 --- a/playfab-docs/multiplayer/networking/release-notes.md +++ b/playfab-docs/multiplayer/networking/release-notes.md @@ -20,6 +20,27 @@ ms.localizationpriority: medium > [!NOTE] > Support for 32-bit Android platforms (arm7 and x86) ended on October 19th, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using the PlayFab Party library on 32-bit Android platforms. +## 1.10.15 + +December 17, 2025 + +- Nintendo Switch 2: Added 10 second timeout for webrequests. + +## 1.10.14 + +December 9, 2025 + +- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has actually expired. +- Android: Added support for 16 KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). + + +## 1.10.13 + +October 14, 2025 + +- Fixed an issue that caused the microphone to not function properly on iOS 26. +- Apple: Added support for Arm64 .xcframework on iOS. + ## 1.10.12 October 6, 2025 diff --git a/playfab-docs/player-progression/game-saves/conflicts.md b/playfab-docs/player-progression/game-saves/conflicts.md index 327424dcc..f152d206d 100644 --- a/playfab-docs/player-progression/game-saves/conflicts.md +++ b/playfab-docs/player-progression/game-saves/conflicts.md @@ -3,32 +3,204 @@ title: Game Saves conflicts author: jasonsandlin description: Game Saves conflicts ms.author: jasonsa -ms.date: 07/01/2025 +ms.date: 01/06/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, game saves ms.localizationpriority: medium --- -## Game Saves conflicts +# Game Saves Conflicts and Atomic Units -Save conflicts occur when the same game data has been modified on multiple devices, and the system needs to determine which version to keep. +## Overview + +Save conflicts occur when the same game data has been modified on multiple devices, and the system needs to determine which version to keep. Understanding how conflicts are detected and resolved is crucial for game developers designing their save data structure. + +## When Conflicts Happen + +Conflicts only occur during the sync operation (`PFGameSaveFilesAddUserWithUiAsync`) when **all** of the following conditions are true: -### When Conflicts Happen -Conflicts only occur during the sync operation (`PFGameSaveFilesAddUserWithUiAsync`) when **both** conditions are true: 1. **Local changes exist**: Files have been modified locally since the last sync 2. **Cloud changes exist**: Another device has uploaded newer data since the last sync +3. **Same atomic unit**: Both changes are in the same root-level folder + +### Conflict Detection Matrix + +| Local Device Changes | Cloud Has Changes in Same Atomic Unit | Result | +|---------------------|--------------------------------------|--------| +| Modified files | Yes | **CONFLICT** | +| Deleted files | Yes | **CONFLICT** | +| No changes | Yes | Download proceeds | +| Modified files | No | Upload proceeds | +| Deleted files | No | Delete proceeds | + +## What is an Atomic Unit? + +Some file sync systems treat conflicts on a file-by-file basis – if the same file needs to be uploaded and also needs to be downloaded, then there's a conflict. In Game Saves, each root-level subfolder is instead treated as an **atomic unit**. + +> **Each root-level subfolder is treated as one atomic unit.** + +If there are any files or subfolders inside a root-level subfolder that need to be downloaded **and** any files or folders in that same root subfolder that need to be uploaded, then the entire atomic unit is in conflict. + +This approach allows you to: +- **Maintain data integrity**: Interdependent files stay consistent together +- **Provide isolation**: Independent data in separate folders can sync without conflicts +- **Minimize conflicts**: Changes to different atomic units on different devices merge automatically + +### Example Save Structure + +``` +SaveRoot/ +├── save.dat ← Atomic unit: root +├── player.dat ← Atomic unit: root +├── Save1/ +│ ├── stats.json ← Atomic unit: Save1 +│ └── inventory.json ← Atomic unit: Save1 +├── Save2/ +│ ├── stats.json ← Atomic unit: Save2 +│ └── inventory.json ← Atomic unit: Save2 +└── WorldState/ + ├── map.dat ← Atomic unit: WorldState + └── npcs/ + └── positions.dat ← Atomic unit: WorldState +``` + +### Conflict Scenarios + +| Device A Changes | Device B Changes | Conflict? | Why | +|-----------------|------------------|-----------|-----| +| `Save1/stats.json` | `Save1/inventory.json` | **YES** | Same atomic unit: Save1 | +| `Save1/stats.json` | `Save2/stats.json` | No | Different units: Save1 vs Save2 | +| `WorldState/map.dat` | `WorldState/npcs/positions.dat` | **YES** | Same atomic unit: WorldState | +| `save.dat` | `Save1/stats.json` | No | Different units: root vs Save1 | +| `player.dat` | `save.dat` | **YES** | Same atomic unit: root | + +## Root-Level Files: Special Case + +**All files at the save root share ONE atomic unit.** + +Files placed directly in the save root (not in any subfolder) are all grouped together as a single atomic unit. If you modify one root-level file locally and another device modifies a different root-level file, this will trigger a conflict. + +| Device A (local) | Device B (cloud) | Same Atomic Unit? | Result | +|-----------------|------------------|-------------------|--------| +| Modifies `rootfile1.txt` | Modifies `rootfile2.txt` | ✅ YES | **CONFLICT** | +| Modifies `rootfile1.txt` | Modifies `save1/config.ini` | ❌ NO | No conflict, both sync | +| Deletes `save.dat` | Modifies `progress.dat` | ✅ YES | **CONFLICT** | + +## User Choice Options -### Conflict Resolution Approach -Some file sync systems treat conflicts on a file-by-file basis – if the same file needs to be uploaded and also needs to be downloaded, then there's a conflict. In Game Saves, each root level subfolder is instead treated as an atomic unit. If there are any files or subfolders inside a root level subfolder that need to be downloaded and any files or folders in that same root subfolder that need to be uploaded, then the entire atomic unit is in conflict. This approach allows you to organize save data so that interdependent data integrity is maintained, while providing isolation between root subfolders for independent data that can be safely merged with changes to other atomic units. By using top level subfolders to structure your game save layout, you can minimize the likelihood of creating a conflict when changes to different atomic units happen on different devices. A slot-based game save system where each slot is a root level subfolder is a very simple example of how these atomic units can be used. -### User Choice Options When conflicts occur, players choose between: -- **Use Local Data**: Keep the device's current save data (overwrites cloud data on next upload) -- **Use Cloud Data**: Download and use the cloud save data (overwrites local data) -A conflict resolution decision applies to all atomic units that are in conflict at the time of sync. If the player chooses cloud, all the conflicting atomic units will be downloaded, and conversely, choosing local leads to all being uploaded. +- **Use Local Data (Keep Local)**: Keep the device's current save data +- **Use Cloud Data (Keep Cloud)**: Download and use the cloud save data + +### Critical: Resolution is All-or-Nothing + +> ⚠️ **Important**: While atomic units determine *when* a conflict is detected, the user's conflict resolution choice applies to the **entire save**, not per-atomic-unit. + +### Example: Mixed Conflict Scenario + +``` +SaveRoot/ +├── SlotA/ ← Local: modified, Cloud: modified → CONFLICT +├── SlotB/ ← Local: modified, Cloud: unchanged → Local-only change +├── SlotC/ ← Local: unchanged, Cloud: modified → Cloud-only change +└── SlotD/ ← Local: modified, Cloud: unchanged → Local-only change +``` + +**User sees conflict prompt** (due to SlotA). + +| User Choice | SlotA | SlotB | SlotC | SlotD | +|-------------|-------|-------|----------|--------------| +| **Keep Local** | ✅ Local kept | ✅ Local uploaded | ❌ Cloud change **LOST** | ✅ Local uploaded | +| **Keep Cloud** | ✅ Cloud downloaded | ❌ Local change **overwritten** | ✅ Cloud downloaded | ❌ Local change **overwritten** | + +### Why This Matters + +1. **Keep Local loses cloud-only changes**: If you choose "Keep Local" because of a conflict in SlotA, you will NOT receive the cloud update to SlotC that another device made. + +2. **Keep Cloud loses local-only changes**: If you choose "Keep Cloud", your local changes to SlotB and SlotD are overwritten by the cloud state. + +3. **Rollback available**: Both choices preserve the discarded branch for future rollback capability. + +### Design Summary + +| Aspect | Granularity | +|--------|-------------| +| Conflict **detection** | Per atomic unit (root subfolder) | +| Conflict **resolution** | Entire save (all-or-nothing) | + +This all-or-nothing approach simplifies the player experience. While per-atomic-unit resolution would technically maintain data consistency (since atomic units define consistency boundaries), it would create user experience challenges: + +- Players would need to understand the concept of atomic units and folder boundaries +- Mixed results (some folders from local, others from cloud) could leave players confused about the final state +- Prompting for each conflicting atomic unit separately would make conflict resolution overwhelming + +By presenting a single "Keep Local" vs "Keep Cloud" choice, players make one clear decision without needing to understand the underlying save structure. + +## When Conflicts Do NOT Occur + +### Delete on Both Sides + +If both devices delete the same file (or files in the same atomic unit), **no conflict occurs**. The system recognizes that both devices agree the file should be removed. + +### Changes in Different Atomic Units + +If Device A modifies files in `SlotA/` and Device B modifies files in `SlotB/`, no conflict occurs. Both changes merge automatically during sync. + +## Best Practices + +### 1. Design Folder Structure Carefully + +Use subfolders for independent save units: + +``` +SaveRoot/ +├── Slot1/ ← Each slot is independent +│ └── save.dat +├── Slot2/ +│ └── save.dat +``` + +A slot-based game save system where each slot is a root-level subfolder is a simple example of how atomic units can be used effectively. + +Other examples include: +- **Shared reference data**: Data that any save slot might use (e.g., unlocked content, achievements) can be stored in its own subfolder, syncing independently from individual save slots +- **Large asset collections**: If your game stores large sets of files that update independently (e.g., downloaded content packs, user-created levels), consider splitting them into multiple root subfolders so updates to one collection don't conflict with updates to another + +### 2. Avoid Root-Level Files for Frequently Modified Data + +Since all root-level files share one atomic unit, avoid placing frequently modified files at the root if they should be independently syncable. + +**Instead of:** +``` +SaveRoot/ +├── autosave.dat ← All root files = 1 atomic unit +└── save1.dat +└── save2.dat +``` + +**Consider:** +``` +SaveRoot/ +├── AutoSave/ +│ └── autosave.dat ← Independent unit +└── Save1/ + └── gamesave.dat ← Independent unit +``` + +### 3. Group Related Data Together + +Files that must stay consistent together should be in the same folder: + +``` +SaveRoot/ +├── Save1/ +│ ├── stats.json ← These files are interdependent +│ ├── inventory.json ← and should conflict together +│ └── quests.json +``` + +### 4. Minimize Conflicts -### Best Practices -- **Design folder structure carefully**: Group related save files into logical folders -- **Minimize conflicts**: Upload frequently to reduce the chance of conflicts -- **Clear conflict UI**: Help players understand what data they might lose with each choice +Upload frequently to reduce the chance of conflicts. The more often you sync, the less likely two devices will have divergent changes. From c2dbf274f5e7b7ca97ad41ddb0fa565d99e59add Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Braulio=20Alp=C3=ADzar?= <152341905+braulioal@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:04:32 -0600 Subject: [PATCH 10/76] Adding missing elements to the links on the menu (#2747) Co-authored-by: edigonzales-microsoft --- playfab-docs/community/leaderboards/index.md | 1 + playfab-docs/community/leaderboards/toc.yml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/playfab-docs/community/leaderboards/index.md b/playfab-docs/community/leaderboards/index.md index c17cf486b..684107747 100644 --- a/playfab-docs/community/leaderboards/index.md +++ b/playfab-docs/community/leaderboards/index.md @@ -72,4 +72,5 @@ has a Statistics engine doing the aggregation. - [API reference](api-reference.md) - [Quota](quota-leaderboards.md) - [Leaderboard meters](../../pricing/Meters/leaderboard-meters.md) +- [Leaderboards and Cloudscript](leaderboards-cloudscript.md). - [Leaderboards With PlayStream and Telemetry](./leaderboards-with-playstream-and-telemetry.md) diff --git a/playfab-docs/community/leaderboards/toc.yml b/playfab-docs/community/leaderboards/toc.yml index fddb12bd9..f5b84daaa 100644 --- a/playfab-docs/community/leaderboards/toc.yml +++ b/playfab-docs/community/leaderboards/toc.yml @@ -25,6 +25,8 @@ items: href: manual-tiers.md - name: Leaderboards with PlayStream and Telemetry href: leaderboards-with-playstream-and-telemetry.md + - name: Leaderboards with Cloud Script + href: leaderboards-cloudscript.md - name: API reference href: api-reference.md - name: Tournaments & Leaderboards (Deprecated) From 499d2f68d258eedb51028711f6e7901a72ede945 Mon Sep 17 00:00:00 2001 From: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:09:03 -0800 Subject: [PATCH 11/76] PF English edits 59226148 (#2745) * pf-english-59226148-09-12-2025-01 * pf-english-59226148-09-15-2025-01 --------- Co-authored-by: edigonzales-microsoft --- .../automation/cloudscript-af/quickstart.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md b/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md index 336735799..777cfeddd 100644 --- a/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md +++ b/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md @@ -19,7 +19,7 @@ In this quickstart, you write a CloudScript using Azure Functions with Visual St There are a couple of steps needed to get started with PlayFab C# CloudScript. - Visit the Visual Studio Code [QuickStart: Create an Azure Functions project using Visual Studio Code](/azure/azure-functions/create-first-function-vs-code-csharp?pivots=programming-language-csharp) and return here once you're set up. The following prerequisites are covered in their quickstart guide: - - An [Azure account](https://azure.microsoft.com/free). Signing up for an Azure Account is free + - An [Azure account](https://azure.microsoft.com/free). Signing up for an Azure Account is free - An [Azure Subscription](/azure/cost-management-billing/manage/create-subscription) - A Functions App resource configured in the Azure portal - To minimize latency of your CloudScript using Azure Functions place them in the *US-West*, *US-West 2*, or *US-West 3* Azure regions. @@ -32,7 +32,7 @@ There are a couple of steps needed to get started with PlayFab C# CloudScript. ## Create an Azure Function -1. Create a basic "HelloWorld" example function. You can see how to do this by following the [Create your first function using Visual Studio Code guide](/azure/azure-functions/functions-create-first-function-vs-code). For a code example using PlayFab variables, see the section below [PlayFab Function Context, Variables and using the Server SDKs](#playfabfunctioncontext). +1. Create a basic "HelloWorld" example function. You can see how to do this by following the [Create your first function using Visual Studio Code guide](/azure/azure-functions/functions-create-first-function-vs-code). For a code example using PlayFab variables, see the section [PlayFab Function Context, Variables, and using the Server SDKs](#playfabfunctioncontext). > [!IMPORTANT] > The "Create your first function using Visual Studio Code" guide instructs you to set the Authorization Level of your Azure Function to `Anonymous`. This is done to simplify testing. @@ -46,7 +46,7 @@ There are a couple of steps needed to get started with PlayFab C# CloudScript. 3. For **Name**, enter a human-friendly name for your function. For **Function URL**, enter the HTTP Trigger URL of the function. The URL can be found in the context menu of the Azure function resource as shown in "Run the function in Azure" section of [Quickstart: Create a function in Azure using Visual Studio Code](/azure/azure-functions/create-first-function-vs-code-csharp?pivots=programming-language-csharp#run-the-function-in-azure). If your Azure Function uses `Function` level authorization, the URL contains the Authorization key. -For more information about deploying Azure functions, see [Deploy Azure Functions from Visual Studio Code](https://code.visualstudio.com/tutorials/functions-extension/deploy-app). +For more information about deploying Azure functions, see [Deploy Azure Functions by using Visual Studio Code](https://learn.microsoft.com/azure/azure-functions/functions-develop-vs-code). ## Using and Calling CloudScript using Azure Functions from your PlayFab Title @@ -144,15 +144,15 @@ private void CallCSharpExecuteFunction() ``` -### PlayFab CloudScript Context, Variables and Server SDKs +### PlayFab CloudScript Context, Variables, and Server SDKs -One advantage of using CloudScript using Azure Functions is that the PlayStream Event and Player Profile context is automatically passed to the Azure Function. On invocation of the CloudScript, you receive the context according to the function's invocation scenario. For example, the context is different depending on whether it was triggered by a PlayStream Action or called directly from the client. This includes information such as the entity profile on whose behalf the CloudScripts was invoked, and potentially the PlayStream events used to invoke the CloudScript. +One advantage of using CloudScript using Azure Functions is that the PlayStream Event and Player Profile context is automatically passed to the Azure Function. On invocation of the CloudScript, you receive the context according to the function's invocation scenario. For example, the context varies depending on whether it's triggered by a PlayStream Action or called directly from the client. This includes information such as the entity profile on whose behalf the CloudScripts was invoked, and potentially the PlayStream events used to invoke the CloudScript. 1. You'll need to install the PlayFab SDK via Package Manager. To do this open Terminal or CMD Console in Visual Studio Code and type: `dotnet add package PlayFabAllSDK` 2. You need to include the [CS2AFHelperClasses.cs](https://github.com/PlayFab/PlayFab-Samples/blob/master/Samples/CSharp/AzureFunctions/CS2AFHelperClasses.cs) file that contains the implementation of `PlayFab.Samples` 3. Execution of a script can occur through several methods (APIs, Scheduled Tasks, PlayStream Event, Segment Entering and Exit method). The context of the execution is important to implement your CloudScript. See the [Using CloudScript context models tutorial](CloudScript-af-context.md) for details on how to use the context of the script. -You can use the HelloWorld example below as your first Azure Function. It invokes an entity API and returns a greeting to the authenticated player. Classic server APIs can be invoked in a similar fashion; however, one would need to specify the title secret key in order to make the call. The secret key can be stored in [application settings](/azure/azure-functions/functions-how-to-use-azure-function-app-settings?tabs=portal#settings) and retrieved using `Environment.GetEnvironmentVariable()` method. +You can use the HelloWorld example as your first Azure Function. It invokes an entity API and returns a greeting to the authenticated player. Classic server APIs can be invoked in a similar fashion; however, one would need to specify the title secret key in order to make the call. The secret key can be stored in [application settings](/azure/azure-functions/functions-how-to-use-azure-function-app-settings?tabs=portal#settings) and retrieved using `Environment.GetEnvironmentVariable()` method. ```c# using PlayFab; @@ -233,7 +233,7 @@ To call the HelloWorld Azure Function from a PlayFab SDK use `ExecuteFunction`. ## Azure Functions in Automation Rules -Azure Functions can also be called by creating rules and scheduled tasks. This works in the same way as our standard CloudScript. To create a rule or scheduled task, go to **Automation** > **Rules** or **Automation** > **Scheduled Tasks**. +Azure Functions can also be called by creating rules and scheduled tasks. This works in the same way as our standard CloudScript. To create a rule or scheduled task, go to **Automation** > **Rules** or **Automation** > **Scheduled Tasks**. - Select **New Rule** - Enter a name for your rule @@ -241,7 +241,7 @@ Azure Functions can also be called by creating rules and scheduled tasks. This - Add an action - From the action dropdown, select **Execute Azure Function** -A list of available Azure Functions that you've registered will be available in the drop-down list. +A list of available Azure Functions that you've registered are available in the drop-down list. ![Configure Rule for Azure Functions](media/azure_function_rules.png) @@ -251,7 +251,7 @@ With Azure functions, you now have the option to debug your CloudScript locally ## Execution limits -CloudScript calls to Azure Functions have timeout limits. If your webhook takes too long to execute, the request will time out in PlayFab. Make sure your code can execute fast enough to stay under the timeout limits. +CloudScript calls to Azure Functions have timeout limits. If your webhook takes too long to execute, the request times out in PlayFab. Make sure your code can execute fast enough to stay under the timeout limits. | Source | Action type | Limit (seconds) | | -------------- | ------------- | --------------: | From 4e52ef7c9130915686cd4557a40603077222e0f5 Mon Sep 17 00:00:00 2001 From: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:11:42 -0800 Subject: [PATCH 12/76] PF English edits 59213568 (#2744) * pf-english-59213568-09-11-2025-01 * pf-english-59213568-09-15-2025-01 --------- Co-authored-by: edigonzales-microsoft --- .../sdks/unity3d/installing-unity3d-sdk.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md b/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md index c88b9c77b..c0bd060e1 100644 --- a/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md +++ b/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md @@ -1,7 +1,7 @@ --- title: Installing the PlayFab SDK Without Editor Extensions for Unity author: DanBehrendt -description: This guide will help you install the PlayFab Unity 3D SDK and configure your project. +description: This guide helps you install the PlayFab Unity 3D SDK and configure your project. ms.author: jenelleb ms.date: 1/25/2020 ms.topic: article @@ -10,17 +10,17 @@ keywords: playfab, unity3d, playfab unity sdk, csharp, unity ms.localizationpriority: medium --- -# Installing the PlayFab SDK Without Editor Extensions for Unity +# Installing the PlayFab SDK without Editor Extensions for Unity You have two options when installing the PlayFab Unity 3D SDK: -- Install the PlayFab Unity Editor Extensions Asset Package. Then use Editor Extension to install the PlayFab Unity 3D SDK and configure your Unity Project. +- Install the PlayFab Unity Editor Extensions Asset Package. Then use Editor Extensions to install the PlayFab Unity 3D SDK and configure your Unity Project. PlayFab Editor Extensions is a stand-alone Unity plug-in that streamlines getting started with PlayFab. - When a supported SDK is installed, additional service menus are available. These menus provide access to SDK configurations. These configuration settings are saved in a combination of places to ensure that the data persists throughout Unity compilations and deployments. + When a supported SDK is installed, other service menus are available. These menus provide access to SDK configurations. These configuration settings are saved in a combination of places to ensure that the data persists throughout Unity compilations and deployments. -- Install the PlayFab Unity 3D SDK directly without using PlayFab Unity Editor Extensions. When you use this installation method, you configure your Unity Project directly by setting properties property values in your code. +- Install the PlayFab Unity 3D SDK directly without using PlayFab Unity Editor Extensions. When you use this installation method, you configure your Unity Project directly by setting the property values in your code. This content assumes you that you have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up) and an existing Unity Project. @@ -30,21 +30,21 @@ To install the SDK without using the PlayFab Unity Editor Extensions: 1. Open your Unity project. 2. Download the [PlayFab Unity3D SDK Asset Package](https://aka.ms/playfabunitysdkdownload) from the PlayFab GitHub repo. -3. Navigate to where you downloaded the file, and double-click on the .UnityPackage file to open the **Import Unity Package** dialog in the Unity Editor. +3. Navigate to where you downloaded the file, and double-click on the UnityPackage file to open the **Import Unity Package** dialog in the Unity Editor. 4. To import the PlayFab Unity3D SDK into your project, select **Import**. -## Setting the Title ID without using the editor extensions +## Setting the Title ID without using the Editor Extensions To set the title: -1. In the Unity Editor Project panel select the **Assets** folder. +1. In the Unity Editor Project panel, select the **Assets** folder. 2. Open the **Assets** > **PlayFabSdk** > **Shared** > **Public** > **Resources** folder. 3. Select the PlayFabSettings Asset. 4. In the **Inspector** window, set the **Title ID**. ![PlayFab Inspector Title ID Setting](media/playfab-shared-settings-title-id.png) -If you are making a server build, be sure to provide the **Developer Secret Key** as well. +If you're making a server build, be sure to provide the **Developer Secret Key** as well. ![PlayFab Developer Secret Key Setting](media/playfab-shared-settings-secret-key.png) From f4ac96dea508b3314eac7b023b22d47e9625f012 Mon Sep 17 00:00:00 2001 From: Yuto Chikazawa <12545287+ychikazawa@users.noreply.github.com> Date: Wed, 14 Jan 2026 09:15:15 +0900 Subject: [PATCH 13/76] Update loginidentityprovider.md (#2730) Co-authored-by: edigonzales-microsoft --- .../events/data-types/loginidentityprovider.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/playfab-docs/api-references/events/data-types/loginidentityprovider.md b/playfab-docs/api-references/events/data-types/loginidentityprovider.md index 13cad61f2..d4e6cc636 100644 --- a/playfab-docs/api-references/events/data-types/loginidentityprovider.md +++ b/playfab-docs/api-references/events/data-types/loginidentityprovider.md @@ -1,9 +1,9 @@ --- title: LoginIdentityProvider -author: joannaleecy +author: yuto chikazawa description: LoginIdentityProvider data type. -ms.author: jenelleb -ms.date: 02/19/2019 +ms.author: ychikazawa +ms.date: 08/19/2025 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events @@ -35,3 +35,9 @@ ms.localizationpriority: medium |NintendoSwitch| |FacebookInstantGames| |OpenIdConnect| +|Apple| +|NintendoSwitchAccount| +|GooglePlayGames| +|XboxMobileStore| +|King| +|BattleNet| From 8d9b0cd72b65a9bfe2cead18816cb31f29742c61 Mon Sep 17 00:00:00 2001 From: Heather Kemp Date: Tue, 13 Jan 2026 16:18:59 -0800 Subject: [PATCH 14/76] fix typo in event name (#2725) Co-authored-by: edigonzales-microsoft --- .../api-references/events/item-moderation-state-changed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playfab-docs/api-references/events/item-moderation-state-changed.md b/playfab-docs/api-references/events/item-moderation-state-changed.md index 388a59382..2afe63c5a 100644 --- a/playfab-docs/api-references/events/item-moderation-state-changed.md +++ b/playfab-docs/api-references/events/item-moderation-state-changed.md @@ -32,7 +32,7 @@ All PlayStream events are formatted as JSON objects and share the following comm |EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| |EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| |EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"tem_moderation_state_changed"| +|EventName|String|"item_moderation_state_changed"| |EventNamespace|String|"playfab.catalog"| |History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| |Reserved|object|Reserved exclusively for PlayFab internal use.| From 05f8428d6e88226a4abe5c06d9828cd3c166b545 Mon Sep 17 00:00:00 2001 From: "learn-build-service-prod[bot]" <113403604+learn-build-service-prod[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:31:18 -0800 Subject: [PATCH 15/76] Resolve syncing conflicts from repo_sync_working_branch to main (#2774) * Update account-upgrades.md - Added new section titled cancel all charges and delete your studio - replaced incorrect links to log in and fixed typos * Update what-is-throttling.md for live branch (#2731) Approved to push to Live * Adding docs to support Battle.net add-on (#2723) * Adding docs to support Battle.net add-on * Updating HTML code * Fixing links and variable instructions * Small grammar updates * PlayFab Unified SDK 2510 Release (#2743) (#2757) * Add docs for PlayFab Unified SDK Preview 1 * Add docs for PlayFab Unified SDK Preview 1 * Add docs for PlayFab Unified SDK Preview 1 * Remove game save references until it hits preview * Update Quickstart - Windows * Update Quickstart - Windows * Update unified SDK quickstart * Update unified SDK quickstart * Update quick start page * Update quick start page * Update quick start page * Update quick start page * Update quick start page * Update TOC * Minor update * Remove redundant LHC entry * Remove SDK vcpkg install option for now * Add Party QS to TOC * Fix typo, remove unused files * Use include for common setup steps * Use include for common setup steps * Use include for common setup steps * Make clear the async and debug articles apply to just core and services, not MLP or party * Update SDK acqusition text * Fix warnings * Fix warnings * Fix warnings * Fix warnings * Fix warnings * Update overview * Add migration guide * Update migration guide * Update quickstart * Rename quickstart for core * Restructure quickstarts * Restructure quickstarts * Update platform table * Update platform table * Add feature readiness table * PR feedback * PR feedback * PR feedback * PR feedback * PR feedback * PR feedback * PR feedback * PR feedback * update documentation to have the build alias playstream events * add remaining documentation for missing mps playstream events * fix spelling * fix build alias * rename mps event pages so that they are aligned with publicly available events, updated index.md and toc * rename the payloads as well + title, description, and links for consistency * fix dates * make keywords uniform, minor fix to index format * Updates for OSS V1 UE5.6 release (#2765) (#2767) * Updates for 5.6 release * Addressing Feedback --------- (cherry picked from commit 749f39a4a2884d0fc9354ebbaa6fa0bb3a0d1806) Co-authored-by: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez Co-authored-by: David Kushmerick <80928711+dkushmerick@users.noreply.github.com> --------- Co-authored-by: Kevin Asgari Co-authored-by: Learn Build Service GitHub App Co-authored-by: kidistadamu Co-authored-by: David Kushmerick <80928711+dkushmerick@users.noreply.github.com> Co-authored-by: Cindy Johnson <88344363+cindyjohnson-msft@users.noreply.github.com> Co-authored-by: Anthony Nguyen <108492711+antnguyen89@users.noreply.github.com> Co-authored-by: kdearnley Co-authored-by: Cody Otterholt Co-authored-by: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> Co-authored-by: Adam Skewgar <32848262+ajskew@users.noreply.github.com> Co-authored-by: yuehanlin <99760142+yuehanlin@users.noreply.github.com> Co-authored-by: Andy McCalib Co-authored-by: Jeffrey Shi Co-authored-by: Valexa Orelien Co-authored-by: edigonzales-microsoft Co-authored-by: Valexa O. <46427879+valexao@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez --- playfab-docs/pricing/account-upgrades.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playfab-docs/pricing/account-upgrades.md b/playfab-docs/pricing/account-upgrades.md index 3e9fe3d86..c52312f0a 100644 --- a/playfab-docs/pricing/account-upgrades.md +++ b/playfab-docs/pricing/account-upgrades.md @@ -38,6 +38,7 @@ You can change your account's plan via Game Manager using the **Plan Recommendat ### Upgrading from Free to Start You can upgrade your account plan at any time on the **My Studios and Titles** page. Use the following steps to upgrade your account from Free to Start. Upgrading an account will upgrade all studios owned by the account. +1. Log in to [http://developer.playfab.com/](http://developer.playfab.com/). 1. Log in to [http://developer.playfab.com/](http://developer.playfab.com/). 2. On the **My Studios and Titles** page, locate the header of a Studio whose linked account should be upgraded. Select **Upgrade Account**. @@ -97,7 +98,6 @@ PlayFab will delete your studio within 10 calendar days following your cancellat Deleting a studio does not delete your PlayFab developer identity. Instead of deleting a studio, you can also delete all titles and change the account plan to Pay as You Go to prevent charges. - ## FAQ **How do I know which subscription plan my account and its associated studios are currently on?** From 54954d46e793b7a196832fdf8617fc377693c19b Mon Sep 17 00:00:00 2001 From: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:30:06 -0800 Subject: [PATCH 16/76] PF trademark edits-60743178 (#2772) * Merge from main * pf-trademark-edits-60743178-01-13-2026-01 * pf-trademark-edits-60743178-01-13-2026-02 --------- Co-authored-by: edigonzales-microsoft --- .../platform-specific-authentication/index.md | 6 +- playfab-docs/sdks/c/index.md | 25 +- playfab-docs/sdks/platforms/playstation.md | 10 +- playfab-docs/sdks/toc.yml | 2 +- .../login-basics-best-practices-01.md | 123 +++++++++ .../test-documents/multiple-logins-01.md | 245 ++++++++++++++++++ 6 files changed, 390 insertions(+), 21 deletions(-) create mode 100644 playfab-docs/test-documents/login-basics-best-practices-01.md create mode 100644 playfab-docs/test-documents/multiple-logins-01.md diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/index.md b/playfab-docs/identity/player-identity/platform-specific-authentication/index.md index a445584bc..d8763996c 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/index.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/index.md @@ -16,7 +16,7 @@ PlayFab supports a wide variety of authentication providers. This allows your ti What this means is that your players can choose how they prefer to verify their identity and sign in using a method that's most natural to them. -Select authentication providers based on what is most meaningful for the players on your target platforms and distribution methods. For example, if your title is released on Xbox, it will make sense to offer Xbox Live sign-in as a way to authenticate their identity. +Select authentication providers based on what is most meaningful for the players on your target platforms and distribution methods. For example, if your title is released on Xbox, it makes sense to offer Xbox Live sign-in as a way to authenticate their identity. ### Apple @@ -41,11 +41,11 @@ Select authentication providers based on what is most meaningful for the players - [Setting up PlayFab authentication using Kongregate and HTML5](kongregate-html5.md) - [Setting up PlayFab authentication using Kongregate and Unity](kongregate-unity.md) -### PlayStation® +### PlayStation®5 / PlayStation®4 - [Setting up PlayFab authentication using PlayStation (secure link)](https://dev.azure.com/PlayFabPrivate/PS5/_git/XPlatCppSdk-Private-PS5?path=%2FGuideToLoginWithPSN.md&_a=preview) -If you're unable to access the above secure link, see [Request access](https://aka.ms/pf-partner-request-access). +If you're unable to access the secure link, see [Request access](https://aka.ms/pf-partner-request-access). "PlayStation" is a registered trademark or trademark of Sony Interactive Entertainment Inc. diff --git a/playfab-docs/sdks/c/index.md b/playfab-docs/sdks/c/index.md index baef72845..15c3395cb 100644 --- a/playfab-docs/sdks/c/index.md +++ b/playfab-docs/sdks/c/index.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # PlayFab Services SDK for C/C++ -The new PlayFab Services SDK for C/C++ is currently available for the following platforms: Win32 (x64 only), Nintendo Switch, Sony PlayStation®, iOS, macOS, Android, Linux, and the Microsoft GDK. Depending on the platform you're targeting, the way you acquire the SDK differs. +The new PlayFab Services SDK for C/C++ is currently available for the following platforms: Win32 (x64 only), Nintendo Switch, PlayStation®5, PlayStation®4, iOS, macOS, Android, Linux, and the Microsoft GDK. Depending on the platform you're targeting, the way you acquire the SDK differs. ## Win32, iOS, macOS, Android, Linux @@ -26,24 +26,24 @@ To learn more about the GDK, see the public documentation: [GDK documentation ho ## Nintendo Switch -Before you can access the PlayFab Services SDK for Nintendo Switch, you need to confirm your registered developer status via the PlayFab page in Nintendo's middleware directory. See more information here: [Request access](../request-access-for-sdks-samples.md). +Before you can access the PlayFab Services SDK for Nintendo Switch, you need to confirm your registered developer status via the PlayFab page in Nintendo's middleware directory. For more information, see [Request access](../request-access-for-sdks-samples.md). Once you've been granted access to the Switch SDK, you can download it from the git repo here: [PlayFabCSdk.Switch](https://dev.azure.com/PlayFabPrivate/Switch/_git/PlayFabCSdk.Switch). -## Sony PlayStation +## PlayStation® -Before you can access the PlayFab Services SDK for PlayStation, you need to confirm your registered developer status via the PlayFab page in Sony's middleware directory. See more information here: [Request access](../request-access-for-sdks-samples.md). +Confirm your developer status on the PlayFab page in the middleware directory of the developer portal before accessing the PlayFab Services SDK for PlayStation. For more information, see [Request access](../request-access-for-sdks-samples.md). Once you've been granted access to the PlayStation SDK, you can download it from the git repo here: [PlayFabCSdk.PS4](https://dev.azure.com/PlayFabPrivate/PS4/_git/PlayFabCSdk.PS4) and [PlayFabCSdk.PS5](https://dev.azure.com/PlayFabPrivate/PS5/_git/PlayFabCSdk.PS5). ## What this SDK includes -The PlayFab Services SDK for C/C++ is for use by a game's runtime components (clients and servers) on Win32 (x64 only), Nintendo Switch, Sony PlayStation®, iOS, macOS, Android, Linux, and the Microsoft GDK. It includes only the subset of feature areas and service calls appropriate for games running on those platforms. +The PlayFab Services SDK for C/C++ is for use by a game's runtime components (clients and servers) on Win32 (x64 only), Nintendo Switch, PlayStation®5, PlayStation®4, iOS, macOS, Android, Linux, and the Microsoft GDK. It includes only the subset of feature areas and service calls appropriate for games running on those platforms. Here are some notable differences when compared to other, more general purpose, PlayFab SDKs: -- The PlayFab Admin API is not included. This SDK is intended to be part of the game runtime (or dedicated server), not for tools or generic services. +- The PlayFab Admin API isn't included. This SDK is intended to be part of the game runtime (or dedicated server), not for tools or generic services. - The PlayFab Server API is only available for select platforms that are used for hosting game servers, specifically Windows, Linux, and macOS. -- The available login methods depend on the platform. For instance, LoginWithApple is only available on Apple devices. +- The available sign in methods depends on the platform. For instance, LoginWithApple is only available on Apple devices. - This SDK removes some older or underutilized feature areas to reduce overall complexity. These areas include economy v1, player stats and leaderboards, and characters. ## Benefits of this SDK @@ -55,11 +55,11 @@ Here are some notable differences when compared to other, more general purpose, ## Platforms supported by this SDK -This SDK is appropriate for x64 Win32 games and game servers, Nintendo Switch games, Sony PlayStation games, iOS games, Android games, macOS games, Linux games, and games utilizing the GDK on Windows and Xbox. +This SDK is appropriate for x64 Win32 games and game servers, Nintendo Switch games, PlayStation games, iOS games, Android games, macOS games, Linux games, and games utilizing the GDK on Windows and Xbox. ## When not to use this SDK -There are scenarios where this SDK is not appropriate: +There are scenarios where this SDK isn't appropriate: - If your game utilizes a game engine for which there's already an engine-specific PlayFab SDK, that SDK is a better fit: [Unreal Engine](../unreal/index.md), [Unity3D](../unity3d/index.md). @@ -77,8 +77,8 @@ There are scenarios where this SDK is not appropriate: - The macOS version of this SDK is available via GitHub. Follow the instructions here to start making basic calls to PlayFab: [Quickstart for macOS](quickstart-macos.md). - Linux - The Linux version of this SDK is available via GitHub. Follow the instructions here to start making basic calls to PlayFab: [Quickstart for Linux](./quickstart-linux.md). -- Sony Playstation - - See [Sony Playstation](#sony-playstation) +- Playstation + - See [Playstation](#playstation) - Nintendo Switch - See [Nintendo Switch](#nintendo-switch) @@ -87,7 +87,8 @@ There are scenarios where this SDK is not appropriate: [API reference documentation](../../api-references/c/pfauthentication/pfauthentication_members.md) "PlayStation" is a registered trademark or trademark of Sony Interactive Entertainment Inc. - + \ No newline at end of file diff --git a/playfab-docs/sdks/platforms/playstation.md b/playfab-docs/sdks/platforms/playstation.md index 8d1a7a948..6f3b1da5c 100644 --- a/playfab-docs/sdks/platforms/playstation.md +++ b/playfab-docs/sdks/platforms/playstation.md @@ -1,7 +1,7 @@ --- -title: PlayFab Services for Sony PlayStation +title: PlayFab Services for PlayStation author: amccalib -description: PlayFab Services SDK options for Sony PlayStation +description: PlayFab Services SDK options for PlayStation ms.author: andmcc ms.date: 06/23/2023 ms.topic: article @@ -12,7 +12,7 @@ ms.localizationpriority: medium # PlayFab Services SDKs for PlayStation®4 and PlayStation®5 -The following SDKs are available for game client development on PS4™ and PS5®. The right SDK depends mostly on your choice of game engine. +The following SDKs are available for game client development on PS4™ and PS5™. The right SDK depends mostly on your choice of game engine. | PlayFab SDK | Description | Learn More | |----------------|-------------|------------| @@ -21,11 +21,11 @@ The following SDKs are available for game client development on PS4™ and PS5® | Unity | Both an editor extension and stand-alone SDK for Unity3d. | [Unity SDK Overview](../unity3d/index.md) | | Legacy C++ | Our older cross-platform C++ SDK supports a simple REST-like interface with PlayFab across multiple platforms. | [Request Access](../request-access-for-sdks-samples.md) | -## Getting Access to SDKs for PS4™ and PS5® +## Getting Access to SDKs for PS4 and PS5 Our PlayFab Services SDKs for Unreal and Unity are platform-agnostic. As such, they require no special access or permissions from PlayFab to utilize on any platform. -To utilize our C/C++ or Legacy C++ SDKs on PS4™ and PS5®, you must confirm your developer status via DevNet. Once you have approval, we can grant access to the SDK. Learn more about this process here: [Request Access](../request-access-for-sdks-samples.md). +To utilize our C/C++ or Legacy C++ SDKs on PS4 and PS5, you must confirm your developer status via DevNet. Once you have approval, we can grant access to the SDK. Learn more about this process here: [Request Access](../request-access-for-sdks-samples.md). "PlayStation" is a registered trademark or trademark of Sony Interactive Entertainment Inc. diff --git a/playfab-docs/sdks/toc.yml b/playfab-docs/sdks/toc.yml index fc4ee4cd1..5d6c16d7a 100644 --- a/playfab-docs/sdks/toc.yml +++ b/playfab-docs/sdks/toc.yml @@ -109,7 +109,7 @@ items: href: platforms/gdk.md - name: Nintendo Switch href: platforms/switch.md - - name: PlayStation + - name: PS5 | PS4 href: platforms/playstation.md - name: Windows href: platforms/windows.md diff --git a/playfab-docs/test-documents/login-basics-best-practices-01.md b/playfab-docs/test-documents/login-basics-best-practices-01.md new file mode 100644 index 000000000..bf8ac253d --- /dev/null +++ b/playfab-docs/test-documents/login-basics-best-practices-01.md @@ -0,0 +1,123 @@ +--- +title: Login basics and best Practices +author: antnguyen89 +description: Describes the basics and Best Practices for login and authentication of players in PlayFab. +ms.author: antnguyen +ms.date: 02/20/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, authentication +ms.localizationpriority: medium +--- + +# Login basics and best practices + +## Platform-specific authentication tutorials + +While all of the platform-specific authentication tutorials demonstrate logging in with [LoginWithCustomID](xref:titleid.playfabapi.com.client.authentication.loginwithcustomid), the uses for this login in a published game are limited to pairing a PlayFab account to a pre-existing database, or another back-end system. + +Otherwise, it's rare for a published title to use a custom ID for a primary login, since in most cases you want to capture additional information on the player's platform. + +### Why we demonstrate this first + +Bluntly - because it's the easiest. A custom ID can be anything, and it makes it easier to call your first API. Once you get serious about developing and releasing your title, it's likely you'll switch to another login mechanism. + +### Best practice + +Unless you know *exactly* why you want `LoginWithCustomId` in your released title, you should migrate to another login mechanism before you launch. + +## Anonymous login mechanisms + +Anonymous login mechanisms are the simplest to use. They require *zero* input from the player, so there's no friction to the first time user experience - and the result is a unique account in PlayFab for each player. *This is the most common login mechanism*. + +These logins include: + +- [LoginWithIOSDeviceID](xref:titleid.playfabapi.com.client.authentication.loginwithiosdeviceid) +- [LoginWithAndroidDeviceID](xref:titleid.playfabapi.com.client.authentication.loginwithandroiddeviceid) +- [LoginWithCustomID](xref:titleid.playfabapi.com.client.authentication.loginwithcustomid) +- [LoginWithNintendoSwitchDeviceId](xref:titleid.playfabapi.com.client.authentication.loginwithnintendoswitchdeviceid) + +Since they're anonymous, these methods can uniquely identify a device, *but contain no recoverable information about the player*. If the player loses or breaks their device, the account is lost, and may be difficult to recover. In most cases the account is orphaned and not retrievable. + +So why use it? Because it's the lowest possible barrier to entry for the player, requiring no interaction. It gets the player trying your game with minimal effort, while creating an account they can get back to for continuity (as long as they have that device). + +### Best practice + +Your game should use an *anonymous* login for creating a new account and linking new devices to an existing account. We recommend this because some players might abandon a game that asks for an e-mail or identifiable information. + +However, once the anonymous login is complete, you should provide the option to add *recoverable* login credentials, and provide some explanation regarding the benefits. + +In particular, you should make sure that paying customers are guided to the *recoverable* login systems, to prevent loss of their accounts. A free account lost forever is a disappointment... + +A paid account lost forever affects revenue. + +### iOS devices + +For iOS devices, the player ID changes if they uninstall your game, and then reinstall it. One way to make sure you have a consistent ID on iOS is to save the device ID for the player to the iTunes KeyChain, so that you can read it from there on game start, and use it to sign in. + +You must determine how to generate unique custom IDs for any other device or platform. Custom IDs are an effective alternative for other platforms or devices, but you must generate your custom IDs with care. If they're too simple, you risk hackers stealing the accounts of others. + +### Android devices + +For latest best practices, see [Google's guidelines on user data IDs](https://developer.android.com/training/articles/user-data-ids). + +> [!NOTE] +> Binding a recoverable login is only required *once* per device. Once bound, the game can continue to use the anonymous login with no drawbacks. See the next section. + +An anonymous login is convenient for the player, but it *isn't* required. Your game can rely exclusively on a recoverable login mechanism. However, your players are happier if they *don't* have to type a password every time they log in. + +## Recoverable login mechanisms + +A *recoverable* login mechanism requires some identity information from the player. As described above, it can be paired with an anonymous login for the best player experience. + +### Pure PlayFab options + +The simplest options are: + +- [LoginWithPlayFab](xref:titleid.playfabapi.com.client.authentication.loginwithplayfab) +- [LoginWithEmailAddress](xref:titleid.playfabapi.com.client.authentication.loginwithemailaddress) + +If used, the e-mail or username-plus-password are authenticated directly by PlayFab. The account is recoverable by the e-mail or username, *even* if the user forgets their password. The login is generally secure (you can implement your own password strength check into your game to improve this). + +### Third party API options + +These require separate API calls to another service, but don't require extra SDK installations: + +- [LoginWithKongregate](xref:titleid.playfabapi.com.client.authentication.loginwithkongregate) +- [LoginWithSteam](xref:titleid.playfabapi.com.client.authentication.loginwithsteam) +- [LoginWithTwitch](xref:titleid.playfabapi.com.client.authentication.loginwithtwitch) +- [LoginWithGameCenter](xref:titleid.playfabapi.com.client.authentication.loginwithgamecenter) (iOS only, and provided you require secure authentication.) + +Secure authentication happens between your user, and the third party service API call. + +### Third party SDK options + +These require a separate SDK installed into your game. Secure authentication happens within the third party SDK. + +- [LoginWithFacebook](xref:titleid.playfabapi.com.client.authentication.loginwithfacebook) +- [LoginWithGoogleAccount](xref:titleid.playfabapi.com.client.authentication.loginwithgoogleaccount) + +In all third party options, those services process the login credentials, and you pass a secure token to the appropriate PlayFab login method. PlayFab remains unaware of the login credentials for those services. + +### More best practices + +Use an appropriate anonymous login for a basic login, and encourage your player to link to a recoverable login. You should pick any one or more of the recoverable mechanisms with which you're comfortable and familiar. + +> [!TIP] +> Account recovery only requires *one* recoverable login, so don't pressure your player to use all of them. + +## Insecure login mechanisms + +One benefit of recoverable login mechanisms is they're more secure than logging in with a custom ID, as they require verified authentication with a third party rather than relying on a user's custom ID remaining a shared secret. + +## Conclusion + +Anonymous login is great, and it provides the user with a fully automated login process. The downside is account recovery, which is sometimes impossible without a recoverable login. + +The following flow chart describes anonymous login followed by adding a recoverable login mechanism. + +![PayFab anonymous login and recoverable login mechanism](../media/tutorials/playfab-anonymous-login-and-recoverable-login.png) + +### Best practice + +Use the appropriate anonymous login for your device, paired with one, or more options for account recovery. diff --git a/playfab-docs/test-documents/multiple-logins-01.md b/playfab-docs/test-documents/multiple-logins-01.md new file mode 100644 index 000000000..d1669b31c --- /dev/null +++ b/playfab-docs/test-documents/multiple-logins-01.md @@ -0,0 +1,245 @@ +--- +title: Handling Multiple PlayFab Logins +author: antnguyen89 +description: Describes how to use SDK features to manage multiple logins from a single client. +ms.author: antnguyen +ms.date: 02/20/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, authentication, sdk, unity, unreal +ms.localizationpriority: medium +--- + +# Handling multiple PlayFab logins + +By default, most PlayFab SDKs cache player login results. This caching can be convenient in the most common scenario when you expect a single player login. In games where you support multiple concurrent players or servers where you manage both players' authentication material and server credentials, that caching can get in the way. To facilitate these scenarios, PlayFab SDKs contain both static and instanced API classes. + +## Static versus instanced API classes + +Most examples and sample code for PlayFab are built using static API classes. In Unity, for example, you might see a reference to __PlayFabClientAPI__. These static classes write to and read from static state within the SDK. Their dependence on static state makes it difficult to use these classes when you're working with multiple players within the same game client. Instanced API classes avoid these problems in exchange for increased management and tracking requirements on your part. In cases where you need to support multiple simultaneous PlayFab logins, we recommend using instanced API classes. + +In the Unity SDK, __PlayFabClientInstanceAPI__ is the instanced version of __PlayFabClientAPI__. All other API classes follow a similar naming pattern. When using the instanced version of an API class, you must create an instance of the class before you can call any methods. To create an instance, you have to specify some extra context. For most classes, the extra required context is just the player's authentication context. In Unity, this context is __PlayFabAuthenticationContext__. Some classes contain login calls. For these calls, you might not have a player's authentication context yet. If that's the case, you only have to provide basic settings like a title ID. These settings are passed in via a __PlayFabApiSettings__ object. + +## Using instanced API classes + +Once you have an instanced API class created with an appropriate authentication context or API settings object, it can be used similarly to a static class. All of the request and response objects are identical. The only difference is that you're responsible for tracking the lifetime of the instance and ensure that any potential callers of PlayFab are provided an appropriate instance. When you're dealing with multiple players, you require multiple instances of any API classes, one per player. It's often easiest to manage these instances encapsulated behind a player object as an owner, but that is left to you. + +Instanced classes that log in a player (such as __PlayFabClientInstanceAPI__) also create and cache the authentication context for that player within the API class instance. This feature allows you to easily reference the authentication context when creating any more classes you need. + +## Unity example + +This sample code demonstrates how multiple players can log in to a game and have independent state tracked in separate class instances. In this example, the API classes and basic functionality are encapsulated behind a simplistic __PlayFabPlayer__ object. When the game starts, we log in two players and then get any data stored in PlayFab for each of those players. + +```csharp +using PlayFab; +using PlayFab.ClientModels; +using PlayFab.DataModels; +using System.Collections.Generic; +using UnityEngine; + +public class PlayFabLogin : MonoBehaviour +{ + PlayFabPlayer player1 = new PlayFabPlayer(); + PlayFabPlayer player2 = new PlayFabPlayer(); + + // Start is called before the first frame update + void Start() + { + if (string.IsNullOrEmpty(PlayFabSettings.staticSettings.TitleId)) + { + // Please change the titleId below to your own titleId from PlayFab Game Manager. + PlayFabSettings.staticSettings.TitleId = ""; + } + + player1.Login("testLogin1"); + player2.Login("testLogin2"); + } + + // Update is called once per frame + void Update() + { + if (player1.loggedIn && !player1.dataLoaded && !player1.dataLoading) + { + player1.LoadData(); + } + if (player2.loggedIn && !player2.dataLoaded && !player2.dataLoading) + { + player2.LoadData(); + } + } +} + +class PlayFabPlayer +{ + public bool loggedIn = false; + public bool dataLoading = false; + public bool dataLoaded = false; + public string PlayFabId; + public Dictionary playerData; + + private PlayFabClientInstanceAPI clientApi; + private PlayFabDataInstanceAPI dataApi; + + public void Login(string customId) + { + clientApi = new PlayFabClientInstanceAPI(PlayFabSettings.staticSettings); + + var request = new LoginWithCustomIDRequest { CustomId = customId, CreateAccount = true }; + + clientApi.LoginWithCustomID(request, result => + { + PlayFabId = result.PlayFabId; + loggedIn = true; + dataApi = new PlayFabDataInstanceAPI(clientApi.authenticationContext); + Debug.Log("Login call succeeded."); + }, error => + { + Debug.LogWarning("Something went wrong with the login call."); + Debug.LogError("Here's some debug information:"); + Debug.LogError(error.GenerateErrorReport()); + }); + } + + public void LoadData() + { + dataLoading = true; + var request = new GetObjectsRequest { Entity = new PlayFab.DataModels.EntityKey { Id = clientApi.authenticationContext.EntityId, Type = clientApi.authenticationContext.EntityType } }; + + dataApi.GetObjects(request, result => + { + playerData = result.Objects; + dataLoaded = true; + dataLoading = false; + Debug.Log("Player data loaded."); + }, error => + { + Debug.LogWarning("Something went wrong with the GetObjects call."); + Debug.LogError("Here's some debug information:"); + Debug.LogError(error.GenerateErrorReport()); + }); + } +} +``` + +## Unreal example + +This code sample demonstrates an actor in Unreal that contains its own PlayFab login context. It shows how to encapsulate PlayFab API instance classes within an __ALoginActor__ class. Multiple __ALoginActor__ instances can be added to a map, given their own CustomIds, and perform PlayFab operations independently. + +LoginActor.h: +```cpp +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "PlayFab.h" +#include "Core/PlayFabError.h" +#include "Core/PlayFabClientDataModels.h" +#include "Core/PlayFabClientAPI.h" +#include "Core/PlayFabDataAPI.h" +#include "LoginActor.generated.h" + +UCLASS() +class MINUE_PF_MARKET_API ALoginActor : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ALoginActor(); + + // Please change the TitleId below to your own TitleId from PlayFab Game Manager. + UPROPERTY(EditAnywhere, config, Category = Settings) + FString TitleId = TEXT(""); + + UPROPERTY(EditAnywhere, config, Category = Settings) + FString CustomId = TEXT("ExampleCustomId"); + +protected: + // Called when the game starts or when spawned + + virtual void BeginPlay() override; + + void OnLoginSuccess(const PlayFab::ClientModels::FLoginResult& Result); + void OnGetObjectsSuccess(const PlayFab::DataModels::FGetObjectsResponse& Result); + void OnError(const PlayFab::FPlayFabCppError& ErrorResult) const; + +public: + bool LoggedIn = false; + + // Called every frame + virtual void Tick(float DeltaTime) override; + + PlayFabClientPtr clientAPI = nullptr; + PlayFabDataPtr dataAPI = nullptr; + + TMap PlayerData; + bool DataLoaded = false; +}; +``` + +LoginActor.cpp: +```cpp +#include "LoginActor.h" + +ALoginActor::ALoginActor() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; +} + +void ALoginActor::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ALoginActor::BeginPlay() +{ + Super::BeginPlay(); + GetMutableDefault()->TitleId = TitleId; + + clientAPI = IPlayFabModuleInterface::Get().GetClientAPI(); + dataAPI = IPlayFabModuleInterface::Get().GetDataAPI(); + + PlayFab::ClientModels::FLoginWithCustomIDRequest request; + request.CustomId = CustomId; + request.CreateAccount = true; + + clientAPI->LoginWithCustomID(request, + PlayFab::UPlayFabClientAPI::FLoginWithCustomIDDelegate::CreateUObject(this, &ALoginActor::OnLoginSuccess), + PlayFab::FPlayFabErrorDelegate::CreateUObject(this, &ALoginActor::OnError) + ); +} + +void ALoginActor::OnLoginSuccess(const PlayFab::ClientModels::FLoginResult& Result) +{ + UE_LOG(LogTemp, Log, TEXT("Login call succeeded.")); + LoggedIn = true; + + PlayFab::DataModels::FGetObjectsRequest dataRequest; + dataRequest.AuthenticationContext = Result.AuthenticationContext; + dataRequest.Entity.Id = Result.EntityToken->Entity->Id; + dataRequest.Entity.Type = Result.EntityToken->Entity->Type; + + dataAPI->GetObjects( + dataRequest, + PlayFab::UPlayFabDataAPI::FGetObjectsDelegate::CreateUObject(this, &ALoginActor::OnGetObjectsSuccess), + PlayFab::FPlayFabErrorDelegate::CreateUObject(this, &ALoginActor::OnError) + ); +} + +void ALoginActor::OnError(const PlayFab::FPlayFabCppError& ErrorResult) const +{ + UE_LOG(LogTemp, Error, TEXT("Something went wrong with your API call.\nHere's some debug information:\n%s"), *ErrorResult.GenerateErrorReport()); +} + +void ALoginActor::OnGetObjectsSuccess(const PlayFab::DataModels::FGetObjectsResponse& Result) +{ + PlayerData = Result.Objects; + DataLoaded = true; + UE_LOG(LogTemp, Log, TEXT("Player data loaded.")); +} +``` + +## Server authentication + +Similar to how instanced API classes allow a game client to handle multiple players, they allow servers to handle a combination of title and player authentication or even multiple titles simultaneously. The basic pattern is nearly identical. Instantiate an API class to handle server login, provide that instance the appropriate __PlayFabApiSettings__ object, and then call an authentication API. If you're on a server, that API is commonly __PlayFabAuthenticationInstanceAPI.GetEntityToken__. Just like a player login, the result of a __GetEntityToken__ call is cached in the API class instance and can be referenced to create more API class instances via the __authenticationContext__ instance property. \ No newline at end of file From eee4c9d77e7ca9c0c03f56308f8c0f425ba748b4 Mon Sep 17 00:00:00 2001 From: edigonzales-microsoft Date: Wed, 14 Jan 2026 14:41:25 -0800 Subject: [PATCH 17/76] Merge Main > Live (Jan 2026) (#2775) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update MPS Playstream event references with changes from playfab-docs (#2766) * Update MPS playstream event references with changes from playfab-docs repo * rm added file * delete old files * update ms author to be microsoft alias * Updates for OSS V1 UE5.6 release (#2765) * Updates for 5.6 release * Addressing Feedback --------- Co-authored-by: Raul Gomez Rodriguez Co-authored-by: David Kushmerick <80928711+dkushmerick@users.noreply.github.com> * Update CODEOWNERS for playfab-docs directory to add Xbox Learning Resources team (#2762) Update CODEOWNERS for playfab-docs directory to add Xbox Learning Resources team https://github.com/orgs/MicrosoftDocs/teams/xbox-learning-resources/members * Xbox Title Add-on Update to enabled PC title linking (#2749) * Updating docs to include xbox live title linking. * Updating index and toc * Updating list of APIs that accept XBL tokens * Fixing doc warnings * Fixing alt text * Updating doc to reflect new UI changes --------- Co-authored-by: edigonzales-microsoft * Increase Acrolinx quality score from 70 to 80 (#2763) Update quality score from 70 to 80, the minimum Acrolinx topic score * Update release-notes.md, PlayFab Party Release Notes [1.10.13][1.10.14] (#2764) * Update release-notes.md * Update release-notes.md * Update release-notes.md --------- Co-authored-by: edigonzales-microsoft * Update master_player_account description in Available built-in entity types page (#2771) * Bug 60687305: PFGameSaves SteamDeck: improve docs based on customer questions around conflict secnarios (#2768) * Bug 60687305: PFGameSaves SteamDeck: improve docs based on customer questions around conflict secnarios * Removed some duplication --------- Co-authored-by: Andy McCalib * Adding missing elements to the links on the menu (#2747) Co-authored-by: edigonzales-microsoft * PF English edits 59226148 (#2745) * pf-english-59226148-09-12-2025-01 * pf-english-59226148-09-15-2025-01 --------- Co-authored-by: edigonzales-microsoft * PF English edits 59213568 (#2744) * pf-english-59213568-09-11-2025-01 * pf-english-59213568-09-15-2025-01 --------- Co-authored-by: edigonzales-microsoft * Update loginidentityprovider.md (#2730) Co-authored-by: edigonzales-microsoft * fix typo in event name (#2725) Co-authored-by: edigonzales-microsoft * Resolve syncing conflicts from repo_sync_working_branch to main (#2774) * Update account-upgrades.md - Added new section titled cancel all charges and delete your studio - replaced incorrect links to log in and fixed typos * Update what-is-throttling.md for live branch (#2731) Approved to push to Live * Adding docs to support Battle.net add-on (#2723) * Adding docs to support Battle.net add-on * Updating HTML code * Fixing links and variable instructions * Small grammar updates * PlayFab Unified SDK 2510 Release (#2743) (#2757) * Add docs for PlayFab Unified SDK Preview 1 * Add docs for PlayFab Unified SDK Preview 1 * Add docs for PlayFab Unified SDK Preview 1 * Remove game save references until it hits preview * Update Quickstart - Windows * Update Quickstart - Windows * Update unified SDK quickstart * Update unified SDK quickstart * Update quick start page * Update quick start page * Update quick start page * Update quick start page * Update quick start page * Update TOC * Minor update * Remove redundant LHC entry * Remove SDK vcpkg install option for now * Add Party QS to TOC * Fix typo, remove unused files * Use include for common setup steps * Use include for common setup steps * Use include for common setup steps * Make clear the async and debug articles apply to just core and services, not MLP or party * Update SDK acqusition text * Fix warnings * Fix warnings * Fix warnings * Fix warnings * Fix warnings * Update overview * Add migration guide * Update migration guide * Update quickstart * Rename quickstart for core * Restructure quickstarts * Restructure quickstarts * Update platform table * Update platform table * Add feature readiness table * PR feedback * PR feedback * PR feedback * PR feedback * PR feedback * PR feedback * PR feedback * PR feedback * update documentation to have the build alias playstream events * add remaining documentation for missing mps playstream events * fix spelling * fix build alias * rename mps event pages so that they are aligned with publicly available events, updated index.md and toc * rename the payloads as well + title, description, and links for consistency * fix dates * make keywords uniform, minor fix to index format * Updates for OSS V1 UE5.6 release (#2765) (#2767) * Updates for 5.6 release * Addressing Feedback --------- (cherry picked from commit 749f39a4a2884d0fc9354ebbaa6fa0bb3a0d1806) Co-authored-by: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez Co-authored-by: David Kushmerick <80928711+dkushmerick@users.noreply.github.com> --------- Co-authored-by: Kevin Asgari Co-authored-by: Learn Build Service GitHub App Co-authored-by: kidistadamu Co-authored-by: David Kushmerick <80928711+dkushmerick@users.noreply.github.com> Co-authored-by: Cindy Johnson <88344363+cindyjohnson-msft@users.noreply.github.com> Co-authored-by: Anthony Nguyen <108492711+antnguyen89@users.noreply.github.com> Co-authored-by: kdearnley Co-authored-by: Cody Otterholt Co-authored-by: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> Co-authored-by: Adam Skewgar <32848262+ajskew@users.noreply.github.com> Co-authored-by: yuehanlin <99760142+yuehanlin@users.noreply.github.com> Co-authored-by: Andy McCalib Co-authored-by: Jeffrey Shi Co-authored-by: Valexa Orelien Co-authored-by: edigonzales-microsoft Co-authored-by: Valexa O. <46427879+valexao@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez * PF trademark edits-60743178 (#2772) * Merge from main * pf-trademark-edits-60743178-01-13-2026-01 * pf-trademark-edits-60743178-01-13-2026-02 --------- Co-authored-by: edigonzales-microsoft --------- Co-authored-by: Valexa O. <46427879+valexao@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez Co-authored-by: David Kushmerick <80928711+dkushmerick@users.noreply.github.com> Co-authored-by: Anthony Nguyen <108492711+antnguyen89@users.noreply.github.com> Co-authored-by: Sebastian Perez-Delgado <46662157+SebastianPD@users.noreply.github.com> Co-authored-by: Cindy Johnson <88344363+cindyjohnson-msft@users.noreply.github.com> Co-authored-by: Jason Sandlin Co-authored-by: Andy McCalib Co-authored-by: Braulio Alpízar <152341905+braulioal@users.noreply.github.com> Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Co-authored-by: Yuto Chikazawa <12545287+ychikazawa@users.noreply.github.com> Co-authored-by: Heather Kemp Co-authored-by: learn-build-service-prod[bot] <113403604+learn-build-service-prod[bot]@users.noreply.github.com> Co-authored-by: Kevin Asgari Co-authored-by: Learn Build Service GitHub App Co-authored-by: kidistadamu Co-authored-by: kdearnley Co-authored-by: Cody Otterholt Co-authored-by: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> Co-authored-by: Adam Skewgar <32848262+ajskew@users.noreply.github.com> Co-authored-by: yuehanlin <99760142+yuehanlin@users.noreply.github.com> Co-authored-by: Jeffrey Shi Co-authored-by: Valexa Orelien --- .../data-types/loginidentityprovider.md | 12 +- .../events/item-moderation-state-changed.md | 2 +- playfab-docs/community/leaderboards/index.md | 1 + playfab-docs/community/leaderboards/toc.yml | 2 + .../platform-specific-authentication/index.md | 6 +- .../automation/cloudscript-af/quickstart.md | 18 +- playfab-docs/pricing/account-upgrades.md | 1 + playfab-docs/sdks/c/index.md | 25 +- playfab-docs/sdks/platforms/playstation.md | 10 +- playfab-docs/sdks/toc.yml | 2 +- .../sdks/unity3d/installing-unity3d-sdk.md | 18 +- .../login-basics-best-practices-01.md | 123 +++++++++ .../test-documents/multiple-logins-01.md | 245 ++++++++++++++++++ 13 files changed, 422 insertions(+), 43 deletions(-) create mode 100644 playfab-docs/test-documents/login-basics-best-practices-01.md create mode 100644 playfab-docs/test-documents/multiple-logins-01.md diff --git a/playfab-docs/api-references/events/data-types/loginidentityprovider.md b/playfab-docs/api-references/events/data-types/loginidentityprovider.md index 13cad61f2..d4e6cc636 100644 --- a/playfab-docs/api-references/events/data-types/loginidentityprovider.md +++ b/playfab-docs/api-references/events/data-types/loginidentityprovider.md @@ -1,9 +1,9 @@ --- title: LoginIdentityProvider -author: joannaleecy +author: yuto chikazawa description: LoginIdentityProvider data type. -ms.author: jenelleb -ms.date: 02/19/2019 +ms.author: ychikazawa +ms.date: 08/19/2025 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events @@ -35,3 +35,9 @@ ms.localizationpriority: medium |NintendoSwitch| |FacebookInstantGames| |OpenIdConnect| +|Apple| +|NintendoSwitchAccount| +|GooglePlayGames| +|XboxMobileStore| +|King| +|BattleNet| diff --git a/playfab-docs/api-references/events/item-moderation-state-changed.md b/playfab-docs/api-references/events/item-moderation-state-changed.md index 388a59382..2afe63c5a 100644 --- a/playfab-docs/api-references/events/item-moderation-state-changed.md +++ b/playfab-docs/api-references/events/item-moderation-state-changed.md @@ -32,7 +32,7 @@ All PlayStream events are formatted as JSON objects and share the following comm |EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| |EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| |EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"tem_moderation_state_changed"| +|EventName|String|"item_moderation_state_changed"| |EventNamespace|String|"playfab.catalog"| |History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| |Reserved|object|Reserved exclusively for PlayFab internal use.| diff --git a/playfab-docs/community/leaderboards/index.md b/playfab-docs/community/leaderboards/index.md index c17cf486b..684107747 100644 --- a/playfab-docs/community/leaderboards/index.md +++ b/playfab-docs/community/leaderboards/index.md @@ -72,4 +72,5 @@ has a Statistics engine doing the aggregation. - [API reference](api-reference.md) - [Quota](quota-leaderboards.md) - [Leaderboard meters](../../pricing/Meters/leaderboard-meters.md) +- [Leaderboards and Cloudscript](leaderboards-cloudscript.md). - [Leaderboards With PlayStream and Telemetry](./leaderboards-with-playstream-and-telemetry.md) diff --git a/playfab-docs/community/leaderboards/toc.yml b/playfab-docs/community/leaderboards/toc.yml index fddb12bd9..f5b84daaa 100644 --- a/playfab-docs/community/leaderboards/toc.yml +++ b/playfab-docs/community/leaderboards/toc.yml @@ -25,6 +25,8 @@ items: href: manual-tiers.md - name: Leaderboards with PlayStream and Telemetry href: leaderboards-with-playstream-and-telemetry.md + - name: Leaderboards with Cloud Script + href: leaderboards-cloudscript.md - name: API reference href: api-reference.md - name: Tournaments & Leaderboards (Deprecated) diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/index.md b/playfab-docs/identity/player-identity/platform-specific-authentication/index.md index a445584bc..d8763996c 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/index.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/index.md @@ -16,7 +16,7 @@ PlayFab supports a wide variety of authentication providers. This allows your ti What this means is that your players can choose how they prefer to verify their identity and sign in using a method that's most natural to them. -Select authentication providers based on what is most meaningful for the players on your target platforms and distribution methods. For example, if your title is released on Xbox, it will make sense to offer Xbox Live sign-in as a way to authenticate their identity. +Select authentication providers based on what is most meaningful for the players on your target platforms and distribution methods. For example, if your title is released on Xbox, it makes sense to offer Xbox Live sign-in as a way to authenticate their identity. ### Apple @@ -41,11 +41,11 @@ Select authentication providers based on what is most meaningful for the players - [Setting up PlayFab authentication using Kongregate and HTML5](kongregate-html5.md) - [Setting up PlayFab authentication using Kongregate and Unity](kongregate-unity.md) -### PlayStation® +### PlayStation®5 / PlayStation®4 - [Setting up PlayFab authentication using PlayStation (secure link)](https://dev.azure.com/PlayFabPrivate/PS5/_git/XPlatCppSdk-Private-PS5?path=%2FGuideToLoginWithPSN.md&_a=preview) -If you're unable to access the above secure link, see [Request access](https://aka.ms/pf-partner-request-access). +If you're unable to access the secure link, see [Request access](https://aka.ms/pf-partner-request-access). "PlayStation" is a registered trademark or trademark of Sony Interactive Entertainment Inc. diff --git a/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md b/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md index 336735799..777cfeddd 100644 --- a/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md +++ b/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md @@ -19,7 +19,7 @@ In this quickstart, you write a CloudScript using Azure Functions with Visual St There are a couple of steps needed to get started with PlayFab C# CloudScript. - Visit the Visual Studio Code [QuickStart: Create an Azure Functions project using Visual Studio Code](/azure/azure-functions/create-first-function-vs-code-csharp?pivots=programming-language-csharp) and return here once you're set up. The following prerequisites are covered in their quickstart guide: - - An [Azure account](https://azure.microsoft.com/free). Signing up for an Azure Account is free + - An [Azure account](https://azure.microsoft.com/free). Signing up for an Azure Account is free - An [Azure Subscription](/azure/cost-management-billing/manage/create-subscription) - A Functions App resource configured in the Azure portal - To minimize latency of your CloudScript using Azure Functions place them in the *US-West*, *US-West 2*, or *US-West 3* Azure regions. @@ -32,7 +32,7 @@ There are a couple of steps needed to get started with PlayFab C# CloudScript. ## Create an Azure Function -1. Create a basic "HelloWorld" example function. You can see how to do this by following the [Create your first function using Visual Studio Code guide](/azure/azure-functions/functions-create-first-function-vs-code). For a code example using PlayFab variables, see the section below [PlayFab Function Context, Variables and using the Server SDKs](#playfabfunctioncontext). +1. Create a basic "HelloWorld" example function. You can see how to do this by following the [Create your first function using Visual Studio Code guide](/azure/azure-functions/functions-create-first-function-vs-code). For a code example using PlayFab variables, see the section [PlayFab Function Context, Variables, and using the Server SDKs](#playfabfunctioncontext). > [!IMPORTANT] > The "Create your first function using Visual Studio Code" guide instructs you to set the Authorization Level of your Azure Function to `Anonymous`. This is done to simplify testing. @@ -46,7 +46,7 @@ There are a couple of steps needed to get started with PlayFab C# CloudScript. 3. For **Name**, enter a human-friendly name for your function. For **Function URL**, enter the HTTP Trigger URL of the function. The URL can be found in the context menu of the Azure function resource as shown in "Run the function in Azure" section of [Quickstart: Create a function in Azure using Visual Studio Code](/azure/azure-functions/create-first-function-vs-code-csharp?pivots=programming-language-csharp#run-the-function-in-azure). If your Azure Function uses `Function` level authorization, the URL contains the Authorization key. -For more information about deploying Azure functions, see [Deploy Azure Functions from Visual Studio Code](https://code.visualstudio.com/tutorials/functions-extension/deploy-app). +For more information about deploying Azure functions, see [Deploy Azure Functions by using Visual Studio Code](https://learn.microsoft.com/azure/azure-functions/functions-develop-vs-code). ## Using and Calling CloudScript using Azure Functions from your PlayFab Title @@ -144,15 +144,15 @@ private void CallCSharpExecuteFunction() ``` -### PlayFab CloudScript Context, Variables and Server SDKs +### PlayFab CloudScript Context, Variables, and Server SDKs -One advantage of using CloudScript using Azure Functions is that the PlayStream Event and Player Profile context is automatically passed to the Azure Function. On invocation of the CloudScript, you receive the context according to the function's invocation scenario. For example, the context is different depending on whether it was triggered by a PlayStream Action or called directly from the client. This includes information such as the entity profile on whose behalf the CloudScripts was invoked, and potentially the PlayStream events used to invoke the CloudScript. +One advantage of using CloudScript using Azure Functions is that the PlayStream Event and Player Profile context is automatically passed to the Azure Function. On invocation of the CloudScript, you receive the context according to the function's invocation scenario. For example, the context varies depending on whether it's triggered by a PlayStream Action or called directly from the client. This includes information such as the entity profile on whose behalf the CloudScripts was invoked, and potentially the PlayStream events used to invoke the CloudScript. 1. You'll need to install the PlayFab SDK via Package Manager. To do this open Terminal or CMD Console in Visual Studio Code and type: `dotnet add package PlayFabAllSDK` 2. You need to include the [CS2AFHelperClasses.cs](https://github.com/PlayFab/PlayFab-Samples/blob/master/Samples/CSharp/AzureFunctions/CS2AFHelperClasses.cs) file that contains the implementation of `PlayFab.Samples` 3. Execution of a script can occur through several methods (APIs, Scheduled Tasks, PlayStream Event, Segment Entering and Exit method). The context of the execution is important to implement your CloudScript. See the [Using CloudScript context models tutorial](CloudScript-af-context.md) for details on how to use the context of the script. -You can use the HelloWorld example below as your first Azure Function. It invokes an entity API and returns a greeting to the authenticated player. Classic server APIs can be invoked in a similar fashion; however, one would need to specify the title secret key in order to make the call. The secret key can be stored in [application settings](/azure/azure-functions/functions-how-to-use-azure-function-app-settings?tabs=portal#settings) and retrieved using `Environment.GetEnvironmentVariable()` method. +You can use the HelloWorld example as your first Azure Function. It invokes an entity API and returns a greeting to the authenticated player. Classic server APIs can be invoked in a similar fashion; however, one would need to specify the title secret key in order to make the call. The secret key can be stored in [application settings](/azure/azure-functions/functions-how-to-use-azure-function-app-settings?tabs=portal#settings) and retrieved using `Environment.GetEnvironmentVariable()` method. ```c# using PlayFab; @@ -233,7 +233,7 @@ To call the HelloWorld Azure Function from a PlayFab SDK use `ExecuteFunction`. ## Azure Functions in Automation Rules -Azure Functions can also be called by creating rules and scheduled tasks. This works in the same way as our standard CloudScript. To create a rule or scheduled task, go to **Automation** > **Rules** or **Automation** > **Scheduled Tasks**. +Azure Functions can also be called by creating rules and scheduled tasks. This works in the same way as our standard CloudScript. To create a rule or scheduled task, go to **Automation** > **Rules** or **Automation** > **Scheduled Tasks**. - Select **New Rule** - Enter a name for your rule @@ -241,7 +241,7 @@ Azure Functions can also be called by creating rules and scheduled tasks. This - Add an action - From the action dropdown, select **Execute Azure Function** -A list of available Azure Functions that you've registered will be available in the drop-down list. +A list of available Azure Functions that you've registered are available in the drop-down list. ![Configure Rule for Azure Functions](media/azure_function_rules.png) @@ -251,7 +251,7 @@ With Azure functions, you now have the option to debug your CloudScript locally ## Execution limits -CloudScript calls to Azure Functions have timeout limits. If your webhook takes too long to execute, the request will time out in PlayFab. Make sure your code can execute fast enough to stay under the timeout limits. +CloudScript calls to Azure Functions have timeout limits. If your webhook takes too long to execute, the request times out in PlayFab. Make sure your code can execute fast enough to stay under the timeout limits. | Source | Action type | Limit (seconds) | | -------------- | ------------- | --------------: | diff --git a/playfab-docs/pricing/account-upgrades.md b/playfab-docs/pricing/account-upgrades.md index 3bd95dd57..c52312f0a 100644 --- a/playfab-docs/pricing/account-upgrades.md +++ b/playfab-docs/pricing/account-upgrades.md @@ -38,6 +38,7 @@ You can change your account's plan via Game Manager using the **Plan Recommendat ### Upgrading from Free to Start You can upgrade your account plan at any time on the **My Studios and Titles** page. Use the following steps to upgrade your account from Free to Start. Upgrading an account will upgrade all studios owned by the account. +1. Log in to [http://developer.playfab.com/](http://developer.playfab.com/). 1. Log in to [http://developer.playfab.com/](http://developer.playfab.com/). 2. On the **My Studios and Titles** page, locate the header of a Studio whose linked account should be upgraded. Select **Upgrade Account**. diff --git a/playfab-docs/sdks/c/index.md b/playfab-docs/sdks/c/index.md index baef72845..15c3395cb 100644 --- a/playfab-docs/sdks/c/index.md +++ b/playfab-docs/sdks/c/index.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # PlayFab Services SDK for C/C++ -The new PlayFab Services SDK for C/C++ is currently available for the following platforms: Win32 (x64 only), Nintendo Switch, Sony PlayStation®, iOS, macOS, Android, Linux, and the Microsoft GDK. Depending on the platform you're targeting, the way you acquire the SDK differs. +The new PlayFab Services SDK for C/C++ is currently available for the following platforms: Win32 (x64 only), Nintendo Switch, PlayStation®5, PlayStation®4, iOS, macOS, Android, Linux, and the Microsoft GDK. Depending on the platform you're targeting, the way you acquire the SDK differs. ## Win32, iOS, macOS, Android, Linux @@ -26,24 +26,24 @@ To learn more about the GDK, see the public documentation: [GDK documentation ho ## Nintendo Switch -Before you can access the PlayFab Services SDK for Nintendo Switch, you need to confirm your registered developer status via the PlayFab page in Nintendo's middleware directory. See more information here: [Request access](../request-access-for-sdks-samples.md). +Before you can access the PlayFab Services SDK for Nintendo Switch, you need to confirm your registered developer status via the PlayFab page in Nintendo's middleware directory. For more information, see [Request access](../request-access-for-sdks-samples.md). Once you've been granted access to the Switch SDK, you can download it from the git repo here: [PlayFabCSdk.Switch](https://dev.azure.com/PlayFabPrivate/Switch/_git/PlayFabCSdk.Switch). -## Sony PlayStation +## PlayStation® -Before you can access the PlayFab Services SDK for PlayStation, you need to confirm your registered developer status via the PlayFab page in Sony's middleware directory. See more information here: [Request access](../request-access-for-sdks-samples.md). +Confirm your developer status on the PlayFab page in the middleware directory of the developer portal before accessing the PlayFab Services SDK for PlayStation. For more information, see [Request access](../request-access-for-sdks-samples.md). Once you've been granted access to the PlayStation SDK, you can download it from the git repo here: [PlayFabCSdk.PS4](https://dev.azure.com/PlayFabPrivate/PS4/_git/PlayFabCSdk.PS4) and [PlayFabCSdk.PS5](https://dev.azure.com/PlayFabPrivate/PS5/_git/PlayFabCSdk.PS5). ## What this SDK includes -The PlayFab Services SDK for C/C++ is for use by a game's runtime components (clients and servers) on Win32 (x64 only), Nintendo Switch, Sony PlayStation®, iOS, macOS, Android, Linux, and the Microsoft GDK. It includes only the subset of feature areas and service calls appropriate for games running on those platforms. +The PlayFab Services SDK for C/C++ is for use by a game's runtime components (clients and servers) on Win32 (x64 only), Nintendo Switch, PlayStation®5, PlayStation®4, iOS, macOS, Android, Linux, and the Microsoft GDK. It includes only the subset of feature areas and service calls appropriate for games running on those platforms. Here are some notable differences when compared to other, more general purpose, PlayFab SDKs: -- The PlayFab Admin API is not included. This SDK is intended to be part of the game runtime (or dedicated server), not for tools or generic services. +- The PlayFab Admin API isn't included. This SDK is intended to be part of the game runtime (or dedicated server), not for tools or generic services. - The PlayFab Server API is only available for select platforms that are used for hosting game servers, specifically Windows, Linux, and macOS. -- The available login methods depend on the platform. For instance, LoginWithApple is only available on Apple devices. +- The available sign in methods depends on the platform. For instance, LoginWithApple is only available on Apple devices. - This SDK removes some older or underutilized feature areas to reduce overall complexity. These areas include economy v1, player stats and leaderboards, and characters. ## Benefits of this SDK @@ -55,11 +55,11 @@ Here are some notable differences when compared to other, more general purpose, ## Platforms supported by this SDK -This SDK is appropriate for x64 Win32 games and game servers, Nintendo Switch games, Sony PlayStation games, iOS games, Android games, macOS games, Linux games, and games utilizing the GDK on Windows and Xbox. +This SDK is appropriate for x64 Win32 games and game servers, Nintendo Switch games, PlayStation games, iOS games, Android games, macOS games, Linux games, and games utilizing the GDK on Windows and Xbox. ## When not to use this SDK -There are scenarios where this SDK is not appropriate: +There are scenarios where this SDK isn't appropriate: - If your game utilizes a game engine for which there's already an engine-specific PlayFab SDK, that SDK is a better fit: [Unreal Engine](../unreal/index.md), [Unity3D](../unity3d/index.md). @@ -77,8 +77,8 @@ There are scenarios where this SDK is not appropriate: - The macOS version of this SDK is available via GitHub. Follow the instructions here to start making basic calls to PlayFab: [Quickstart for macOS](quickstart-macos.md). - Linux - The Linux version of this SDK is available via GitHub. Follow the instructions here to start making basic calls to PlayFab: [Quickstart for Linux](./quickstart-linux.md). -- Sony Playstation - - See [Sony Playstation](#sony-playstation) +- Playstation + - See [Playstation](#playstation) - Nintendo Switch - See [Nintendo Switch](#nintendo-switch) @@ -87,7 +87,8 @@ There are scenarios where this SDK is not appropriate: [API reference documentation](../../api-references/c/pfauthentication/pfauthentication_members.md) "PlayStation" is a registered trademark or trademark of Sony Interactive Entertainment Inc. - + \ No newline at end of file diff --git a/playfab-docs/sdks/platforms/playstation.md b/playfab-docs/sdks/platforms/playstation.md index 8d1a7a948..6f3b1da5c 100644 --- a/playfab-docs/sdks/platforms/playstation.md +++ b/playfab-docs/sdks/platforms/playstation.md @@ -1,7 +1,7 @@ --- -title: PlayFab Services for Sony PlayStation +title: PlayFab Services for PlayStation author: amccalib -description: PlayFab Services SDK options for Sony PlayStation +description: PlayFab Services SDK options for PlayStation ms.author: andmcc ms.date: 06/23/2023 ms.topic: article @@ -12,7 +12,7 @@ ms.localizationpriority: medium # PlayFab Services SDKs for PlayStation®4 and PlayStation®5 -The following SDKs are available for game client development on PS4™ and PS5®. The right SDK depends mostly on your choice of game engine. +The following SDKs are available for game client development on PS4™ and PS5™. The right SDK depends mostly on your choice of game engine. | PlayFab SDK | Description | Learn More | |----------------|-------------|------------| @@ -21,11 +21,11 @@ The following SDKs are available for game client development on PS4™ and PS5® | Unity | Both an editor extension and stand-alone SDK for Unity3d. | [Unity SDK Overview](../unity3d/index.md) | | Legacy C++ | Our older cross-platform C++ SDK supports a simple REST-like interface with PlayFab across multiple platforms. | [Request Access](../request-access-for-sdks-samples.md) | -## Getting Access to SDKs for PS4™ and PS5® +## Getting Access to SDKs for PS4 and PS5 Our PlayFab Services SDKs for Unreal and Unity are platform-agnostic. As such, they require no special access or permissions from PlayFab to utilize on any platform. -To utilize our C/C++ or Legacy C++ SDKs on PS4™ and PS5®, you must confirm your developer status via DevNet. Once you have approval, we can grant access to the SDK. Learn more about this process here: [Request Access](../request-access-for-sdks-samples.md). +To utilize our C/C++ or Legacy C++ SDKs on PS4 and PS5, you must confirm your developer status via DevNet. Once you have approval, we can grant access to the SDK. Learn more about this process here: [Request Access](../request-access-for-sdks-samples.md). "PlayStation" is a registered trademark or trademark of Sony Interactive Entertainment Inc. diff --git a/playfab-docs/sdks/toc.yml b/playfab-docs/sdks/toc.yml index fc4ee4cd1..5d6c16d7a 100644 --- a/playfab-docs/sdks/toc.yml +++ b/playfab-docs/sdks/toc.yml @@ -109,7 +109,7 @@ items: href: platforms/gdk.md - name: Nintendo Switch href: platforms/switch.md - - name: PlayStation + - name: PS5 | PS4 href: platforms/playstation.md - name: Windows href: platforms/windows.md diff --git a/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md b/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md index c88b9c77b..c0bd060e1 100644 --- a/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md +++ b/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md @@ -1,7 +1,7 @@ --- title: Installing the PlayFab SDK Without Editor Extensions for Unity author: DanBehrendt -description: This guide will help you install the PlayFab Unity 3D SDK and configure your project. +description: This guide helps you install the PlayFab Unity 3D SDK and configure your project. ms.author: jenelleb ms.date: 1/25/2020 ms.topic: article @@ -10,17 +10,17 @@ keywords: playfab, unity3d, playfab unity sdk, csharp, unity ms.localizationpriority: medium --- -# Installing the PlayFab SDK Without Editor Extensions for Unity +# Installing the PlayFab SDK without Editor Extensions for Unity You have two options when installing the PlayFab Unity 3D SDK: -- Install the PlayFab Unity Editor Extensions Asset Package. Then use Editor Extension to install the PlayFab Unity 3D SDK and configure your Unity Project. +- Install the PlayFab Unity Editor Extensions Asset Package. Then use Editor Extensions to install the PlayFab Unity 3D SDK and configure your Unity Project. PlayFab Editor Extensions is a stand-alone Unity plug-in that streamlines getting started with PlayFab. - When a supported SDK is installed, additional service menus are available. These menus provide access to SDK configurations. These configuration settings are saved in a combination of places to ensure that the data persists throughout Unity compilations and deployments. + When a supported SDK is installed, other service menus are available. These menus provide access to SDK configurations. These configuration settings are saved in a combination of places to ensure that the data persists throughout Unity compilations and deployments. -- Install the PlayFab Unity 3D SDK directly without using PlayFab Unity Editor Extensions. When you use this installation method, you configure your Unity Project directly by setting properties property values in your code. +- Install the PlayFab Unity 3D SDK directly without using PlayFab Unity Editor Extensions. When you use this installation method, you configure your Unity Project directly by setting the property values in your code. This content assumes you that you have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up) and an existing Unity Project. @@ -30,21 +30,21 @@ To install the SDK without using the PlayFab Unity Editor Extensions: 1. Open your Unity project. 2. Download the [PlayFab Unity3D SDK Asset Package](https://aka.ms/playfabunitysdkdownload) from the PlayFab GitHub repo. -3. Navigate to where you downloaded the file, and double-click on the .UnityPackage file to open the **Import Unity Package** dialog in the Unity Editor. +3. Navigate to where you downloaded the file, and double-click on the UnityPackage file to open the **Import Unity Package** dialog in the Unity Editor. 4. To import the PlayFab Unity3D SDK into your project, select **Import**. -## Setting the Title ID without using the editor extensions +## Setting the Title ID without using the Editor Extensions To set the title: -1. In the Unity Editor Project panel select the **Assets** folder. +1. In the Unity Editor Project panel, select the **Assets** folder. 2. Open the **Assets** > **PlayFabSdk** > **Shared** > **Public** > **Resources** folder. 3. Select the PlayFabSettings Asset. 4. In the **Inspector** window, set the **Title ID**. ![PlayFab Inspector Title ID Setting](media/playfab-shared-settings-title-id.png) -If you are making a server build, be sure to provide the **Developer Secret Key** as well. +If you're making a server build, be sure to provide the **Developer Secret Key** as well. ![PlayFab Developer Secret Key Setting](media/playfab-shared-settings-secret-key.png) diff --git a/playfab-docs/test-documents/login-basics-best-practices-01.md b/playfab-docs/test-documents/login-basics-best-practices-01.md new file mode 100644 index 000000000..bf8ac253d --- /dev/null +++ b/playfab-docs/test-documents/login-basics-best-practices-01.md @@ -0,0 +1,123 @@ +--- +title: Login basics and best Practices +author: antnguyen89 +description: Describes the basics and Best Practices for login and authentication of players in PlayFab. +ms.author: antnguyen +ms.date: 02/20/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, authentication +ms.localizationpriority: medium +--- + +# Login basics and best practices + +## Platform-specific authentication tutorials + +While all of the platform-specific authentication tutorials demonstrate logging in with [LoginWithCustomID](xref:titleid.playfabapi.com.client.authentication.loginwithcustomid), the uses for this login in a published game are limited to pairing a PlayFab account to a pre-existing database, or another back-end system. + +Otherwise, it's rare for a published title to use a custom ID for a primary login, since in most cases you want to capture additional information on the player's platform. + +### Why we demonstrate this first + +Bluntly - because it's the easiest. A custom ID can be anything, and it makes it easier to call your first API. Once you get serious about developing and releasing your title, it's likely you'll switch to another login mechanism. + +### Best practice + +Unless you know *exactly* why you want `LoginWithCustomId` in your released title, you should migrate to another login mechanism before you launch. + +## Anonymous login mechanisms + +Anonymous login mechanisms are the simplest to use. They require *zero* input from the player, so there's no friction to the first time user experience - and the result is a unique account in PlayFab for each player. *This is the most common login mechanism*. + +These logins include: + +- [LoginWithIOSDeviceID](xref:titleid.playfabapi.com.client.authentication.loginwithiosdeviceid) +- [LoginWithAndroidDeviceID](xref:titleid.playfabapi.com.client.authentication.loginwithandroiddeviceid) +- [LoginWithCustomID](xref:titleid.playfabapi.com.client.authentication.loginwithcustomid) +- [LoginWithNintendoSwitchDeviceId](xref:titleid.playfabapi.com.client.authentication.loginwithnintendoswitchdeviceid) + +Since they're anonymous, these methods can uniquely identify a device, *but contain no recoverable information about the player*. If the player loses or breaks their device, the account is lost, and may be difficult to recover. In most cases the account is orphaned and not retrievable. + +So why use it? Because it's the lowest possible barrier to entry for the player, requiring no interaction. It gets the player trying your game with minimal effort, while creating an account they can get back to for continuity (as long as they have that device). + +### Best practice + +Your game should use an *anonymous* login for creating a new account and linking new devices to an existing account. We recommend this because some players might abandon a game that asks for an e-mail or identifiable information. + +However, once the anonymous login is complete, you should provide the option to add *recoverable* login credentials, and provide some explanation regarding the benefits. + +In particular, you should make sure that paying customers are guided to the *recoverable* login systems, to prevent loss of their accounts. A free account lost forever is a disappointment... + +A paid account lost forever affects revenue. + +### iOS devices + +For iOS devices, the player ID changes if they uninstall your game, and then reinstall it. One way to make sure you have a consistent ID on iOS is to save the device ID for the player to the iTunes KeyChain, so that you can read it from there on game start, and use it to sign in. + +You must determine how to generate unique custom IDs for any other device or platform. Custom IDs are an effective alternative for other platforms or devices, but you must generate your custom IDs with care. If they're too simple, you risk hackers stealing the accounts of others. + +### Android devices + +For latest best practices, see [Google's guidelines on user data IDs](https://developer.android.com/training/articles/user-data-ids). + +> [!NOTE] +> Binding a recoverable login is only required *once* per device. Once bound, the game can continue to use the anonymous login with no drawbacks. See the next section. + +An anonymous login is convenient for the player, but it *isn't* required. Your game can rely exclusively on a recoverable login mechanism. However, your players are happier if they *don't* have to type a password every time they log in. + +## Recoverable login mechanisms + +A *recoverable* login mechanism requires some identity information from the player. As described above, it can be paired with an anonymous login for the best player experience. + +### Pure PlayFab options + +The simplest options are: + +- [LoginWithPlayFab](xref:titleid.playfabapi.com.client.authentication.loginwithplayfab) +- [LoginWithEmailAddress](xref:titleid.playfabapi.com.client.authentication.loginwithemailaddress) + +If used, the e-mail or username-plus-password are authenticated directly by PlayFab. The account is recoverable by the e-mail or username, *even* if the user forgets their password. The login is generally secure (you can implement your own password strength check into your game to improve this). + +### Third party API options + +These require separate API calls to another service, but don't require extra SDK installations: + +- [LoginWithKongregate](xref:titleid.playfabapi.com.client.authentication.loginwithkongregate) +- [LoginWithSteam](xref:titleid.playfabapi.com.client.authentication.loginwithsteam) +- [LoginWithTwitch](xref:titleid.playfabapi.com.client.authentication.loginwithtwitch) +- [LoginWithGameCenter](xref:titleid.playfabapi.com.client.authentication.loginwithgamecenter) (iOS only, and provided you require secure authentication.) + +Secure authentication happens between your user, and the third party service API call. + +### Third party SDK options + +These require a separate SDK installed into your game. Secure authentication happens within the third party SDK. + +- [LoginWithFacebook](xref:titleid.playfabapi.com.client.authentication.loginwithfacebook) +- [LoginWithGoogleAccount](xref:titleid.playfabapi.com.client.authentication.loginwithgoogleaccount) + +In all third party options, those services process the login credentials, and you pass a secure token to the appropriate PlayFab login method. PlayFab remains unaware of the login credentials for those services. + +### More best practices + +Use an appropriate anonymous login for a basic login, and encourage your player to link to a recoverable login. You should pick any one or more of the recoverable mechanisms with which you're comfortable and familiar. + +> [!TIP] +> Account recovery only requires *one* recoverable login, so don't pressure your player to use all of them. + +## Insecure login mechanisms + +One benefit of recoverable login mechanisms is they're more secure than logging in with a custom ID, as they require verified authentication with a third party rather than relying on a user's custom ID remaining a shared secret. + +## Conclusion + +Anonymous login is great, and it provides the user with a fully automated login process. The downside is account recovery, which is sometimes impossible without a recoverable login. + +The following flow chart describes anonymous login followed by adding a recoverable login mechanism. + +![PayFab anonymous login and recoverable login mechanism](../media/tutorials/playfab-anonymous-login-and-recoverable-login.png) + +### Best practice + +Use the appropriate anonymous login for your device, paired with one, or more options for account recovery. diff --git a/playfab-docs/test-documents/multiple-logins-01.md b/playfab-docs/test-documents/multiple-logins-01.md new file mode 100644 index 000000000..d1669b31c --- /dev/null +++ b/playfab-docs/test-documents/multiple-logins-01.md @@ -0,0 +1,245 @@ +--- +title: Handling Multiple PlayFab Logins +author: antnguyen89 +description: Describes how to use SDK features to manage multiple logins from a single client. +ms.author: antnguyen +ms.date: 02/20/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, authentication, sdk, unity, unreal +ms.localizationpriority: medium +--- + +# Handling multiple PlayFab logins + +By default, most PlayFab SDKs cache player login results. This caching can be convenient in the most common scenario when you expect a single player login. In games where you support multiple concurrent players or servers where you manage both players' authentication material and server credentials, that caching can get in the way. To facilitate these scenarios, PlayFab SDKs contain both static and instanced API classes. + +## Static versus instanced API classes + +Most examples and sample code for PlayFab are built using static API classes. In Unity, for example, you might see a reference to __PlayFabClientAPI__. These static classes write to and read from static state within the SDK. Their dependence on static state makes it difficult to use these classes when you're working with multiple players within the same game client. Instanced API classes avoid these problems in exchange for increased management and tracking requirements on your part. In cases where you need to support multiple simultaneous PlayFab logins, we recommend using instanced API classes. + +In the Unity SDK, __PlayFabClientInstanceAPI__ is the instanced version of __PlayFabClientAPI__. All other API classes follow a similar naming pattern. When using the instanced version of an API class, you must create an instance of the class before you can call any methods. To create an instance, you have to specify some extra context. For most classes, the extra required context is just the player's authentication context. In Unity, this context is __PlayFabAuthenticationContext__. Some classes contain login calls. For these calls, you might not have a player's authentication context yet. If that's the case, you only have to provide basic settings like a title ID. These settings are passed in via a __PlayFabApiSettings__ object. + +## Using instanced API classes + +Once you have an instanced API class created with an appropriate authentication context or API settings object, it can be used similarly to a static class. All of the request and response objects are identical. The only difference is that you're responsible for tracking the lifetime of the instance and ensure that any potential callers of PlayFab are provided an appropriate instance. When you're dealing with multiple players, you require multiple instances of any API classes, one per player. It's often easiest to manage these instances encapsulated behind a player object as an owner, but that is left to you. + +Instanced classes that log in a player (such as __PlayFabClientInstanceAPI__) also create and cache the authentication context for that player within the API class instance. This feature allows you to easily reference the authentication context when creating any more classes you need. + +## Unity example + +This sample code demonstrates how multiple players can log in to a game and have independent state tracked in separate class instances. In this example, the API classes and basic functionality are encapsulated behind a simplistic __PlayFabPlayer__ object. When the game starts, we log in two players and then get any data stored in PlayFab for each of those players. + +```csharp +using PlayFab; +using PlayFab.ClientModels; +using PlayFab.DataModels; +using System.Collections.Generic; +using UnityEngine; + +public class PlayFabLogin : MonoBehaviour +{ + PlayFabPlayer player1 = new PlayFabPlayer(); + PlayFabPlayer player2 = new PlayFabPlayer(); + + // Start is called before the first frame update + void Start() + { + if (string.IsNullOrEmpty(PlayFabSettings.staticSettings.TitleId)) + { + // Please change the titleId below to your own titleId from PlayFab Game Manager. + PlayFabSettings.staticSettings.TitleId = ""; + } + + player1.Login("testLogin1"); + player2.Login("testLogin2"); + } + + // Update is called once per frame + void Update() + { + if (player1.loggedIn && !player1.dataLoaded && !player1.dataLoading) + { + player1.LoadData(); + } + if (player2.loggedIn && !player2.dataLoaded && !player2.dataLoading) + { + player2.LoadData(); + } + } +} + +class PlayFabPlayer +{ + public bool loggedIn = false; + public bool dataLoading = false; + public bool dataLoaded = false; + public string PlayFabId; + public Dictionary playerData; + + private PlayFabClientInstanceAPI clientApi; + private PlayFabDataInstanceAPI dataApi; + + public void Login(string customId) + { + clientApi = new PlayFabClientInstanceAPI(PlayFabSettings.staticSettings); + + var request = new LoginWithCustomIDRequest { CustomId = customId, CreateAccount = true }; + + clientApi.LoginWithCustomID(request, result => + { + PlayFabId = result.PlayFabId; + loggedIn = true; + dataApi = new PlayFabDataInstanceAPI(clientApi.authenticationContext); + Debug.Log("Login call succeeded."); + }, error => + { + Debug.LogWarning("Something went wrong with the login call."); + Debug.LogError("Here's some debug information:"); + Debug.LogError(error.GenerateErrorReport()); + }); + } + + public void LoadData() + { + dataLoading = true; + var request = new GetObjectsRequest { Entity = new PlayFab.DataModels.EntityKey { Id = clientApi.authenticationContext.EntityId, Type = clientApi.authenticationContext.EntityType } }; + + dataApi.GetObjects(request, result => + { + playerData = result.Objects; + dataLoaded = true; + dataLoading = false; + Debug.Log("Player data loaded."); + }, error => + { + Debug.LogWarning("Something went wrong with the GetObjects call."); + Debug.LogError("Here's some debug information:"); + Debug.LogError(error.GenerateErrorReport()); + }); + } +} +``` + +## Unreal example + +This code sample demonstrates an actor in Unreal that contains its own PlayFab login context. It shows how to encapsulate PlayFab API instance classes within an __ALoginActor__ class. Multiple __ALoginActor__ instances can be added to a map, given their own CustomIds, and perform PlayFab operations independently. + +LoginActor.h: +```cpp +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "PlayFab.h" +#include "Core/PlayFabError.h" +#include "Core/PlayFabClientDataModels.h" +#include "Core/PlayFabClientAPI.h" +#include "Core/PlayFabDataAPI.h" +#include "LoginActor.generated.h" + +UCLASS() +class MINUE_PF_MARKET_API ALoginActor : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + ALoginActor(); + + // Please change the TitleId below to your own TitleId from PlayFab Game Manager. + UPROPERTY(EditAnywhere, config, Category = Settings) + FString TitleId = TEXT(""); + + UPROPERTY(EditAnywhere, config, Category = Settings) + FString CustomId = TEXT("ExampleCustomId"); + +protected: + // Called when the game starts or when spawned + + virtual void BeginPlay() override; + + void OnLoginSuccess(const PlayFab::ClientModels::FLoginResult& Result); + void OnGetObjectsSuccess(const PlayFab::DataModels::FGetObjectsResponse& Result); + void OnError(const PlayFab::FPlayFabCppError& ErrorResult) const; + +public: + bool LoggedIn = false; + + // Called every frame + virtual void Tick(float DeltaTime) override; + + PlayFabClientPtr clientAPI = nullptr; + PlayFabDataPtr dataAPI = nullptr; + + TMap PlayerData; + bool DataLoaded = false; +}; +``` + +LoginActor.cpp: +```cpp +#include "LoginActor.h" + +ALoginActor::ALoginActor() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; +} + +void ALoginActor::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +void ALoginActor::BeginPlay() +{ + Super::BeginPlay(); + GetMutableDefault()->TitleId = TitleId; + + clientAPI = IPlayFabModuleInterface::Get().GetClientAPI(); + dataAPI = IPlayFabModuleInterface::Get().GetDataAPI(); + + PlayFab::ClientModels::FLoginWithCustomIDRequest request; + request.CustomId = CustomId; + request.CreateAccount = true; + + clientAPI->LoginWithCustomID(request, + PlayFab::UPlayFabClientAPI::FLoginWithCustomIDDelegate::CreateUObject(this, &ALoginActor::OnLoginSuccess), + PlayFab::FPlayFabErrorDelegate::CreateUObject(this, &ALoginActor::OnError) + ); +} + +void ALoginActor::OnLoginSuccess(const PlayFab::ClientModels::FLoginResult& Result) +{ + UE_LOG(LogTemp, Log, TEXT("Login call succeeded.")); + LoggedIn = true; + + PlayFab::DataModels::FGetObjectsRequest dataRequest; + dataRequest.AuthenticationContext = Result.AuthenticationContext; + dataRequest.Entity.Id = Result.EntityToken->Entity->Id; + dataRequest.Entity.Type = Result.EntityToken->Entity->Type; + + dataAPI->GetObjects( + dataRequest, + PlayFab::UPlayFabDataAPI::FGetObjectsDelegate::CreateUObject(this, &ALoginActor::OnGetObjectsSuccess), + PlayFab::FPlayFabErrorDelegate::CreateUObject(this, &ALoginActor::OnError) + ); +} + +void ALoginActor::OnError(const PlayFab::FPlayFabCppError& ErrorResult) const +{ + UE_LOG(LogTemp, Error, TEXT("Something went wrong with your API call.\nHere's some debug information:\n%s"), *ErrorResult.GenerateErrorReport()); +} + +void ALoginActor::OnGetObjectsSuccess(const PlayFab::DataModels::FGetObjectsResponse& Result) +{ + PlayerData = Result.Objects; + DataLoaded = true; + UE_LOG(LogTemp, Log, TEXT("Player data loaded.")); +} +``` + +## Server authentication + +Similar to how instanced API classes allow a game client to handle multiple players, they allow servers to handle a combination of title and player authentication or even multiple titles simultaneously. The basic pattern is nearly identical. Instantiate an API class to handle server login, provide that instance the appropriate __PlayFabApiSettings__ object, and then call an authentication API. If you're on a server, that API is commonly __PlayFabAuthenticationInstanceAPI.GetEntityToken__. Just like a player login, the result of a __GetEntityToken__ call is cached in the API class instance and can be referenced to create more API class instances via the __authenticationContext__ instance property. \ No newline at end of file From c08c72a51f608161fd601779848490b9b8b167d1 Mon Sep 17 00:00:00 2001 From: Cindy Johnson <88344363+cindyjohnson-msft@users.noreply.github.com> Date: Wed, 21 Jan 2026 09:13:56 -0800 Subject: [PATCH 18/76] Update webhook calls documentation with IP allowlisting info (#2777) * Update webhook calls documentation with IP allowlisting info Added note about allowing IP addresses for outbound CloudScript calls. * update formatting Added note about allowlisting IP addresses for outbound CloudScript calls. * update wording --- .../cloudscript/making-webhook-calls-from-cloudscript.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/playfab-docs/live-service-management/service-gateway/automation/cloudscript/making-webhook-calls-from-cloudscript.md b/playfab-docs/live-service-management/service-gateway/automation/cloudscript/making-webhook-calls-from-cloudscript.md index 2b45c7de9..27c1c1e13 100644 --- a/playfab-docs/live-service-management/service-gateway/automation/cloudscript/making-webhook-calls-from-cloudscript.md +++ b/playfab-docs/live-service-management/service-gateway/automation/cloudscript/making-webhook-calls-from-cloudscript.md @@ -22,6 +22,9 @@ This allows titles to make calls to basic informational services, but it *also* This tutorial discusses making Webhook calls from CloudScript, for both *nonsecure* and *secure* scenarios. +> [!NOTE] +> You can refer to the 'PlayFab static IP prefixes and addresses' section of the API Features page in the Developer Portal if you need to allowlist IP addresses used for outbound CloudScript calls. + As a REST call, the structure of a Webhook call from CloudScript is simple. The elements to be specified are: - The URL endpoint. From 2185aea8b2101a4c450899546257e3ec4c41f603 Mon Sep 17 00:00:00 2001 From: "Valexa O." <46427879+valexao@users.noreply.github.com> Date: Thu, 22 Jan 2026 10:33:30 -0800 Subject: [PATCH 19/76] Add a common properties docfx template for Playstream Events Common Properties (#2776) * add a common properties docfx template and replace common properties section * create a common properties v1 and v2 + update MPS properties to not be redundant * update all v2 events with correct payload * update the rest of the events to use common-properties-eventsv1 * fix links --- .../events/auth-token-validated.md | 16 +------------- .../events/build-alias-created.md | 20 +----------------- .../events/build-alias-deleted.md | 19 +---------------- .../events/build-alias-updated.md | 19 +---------------- .../api-references/events/build-deleted.md | 19 +---------------- .../events/build-region-status-changed.md | 19 +---------------- .../events/build-region-updated.md | 19 +---------------- .../events/build-region-utilization.md | 19 +---------------- .../events/certificate-deleted.md | 19 +---------------- .../events/certificate-uploaded.md | 19 +---------------- .../events/character-consumed-item.md | 16 +------------- .../events/character-created.md | 16 +------------- .../events/character-inventory-item-added.md | 16 +------------- .../events/character-statistic-changed.md | 16 +------------- .../events/character-statistic-deleted.md | 16 +------------- .../events/character-vc-item-purchased.md | 16 +------------- ...racter-virtual-currency-balance-changed.md | 16 +------------- .../events/client-focus-change.md | 16 +------------- .../events/client-session-start.md | 16 +------------- .../api-references/events/crash-detected.md | 19 +---------------- .../events/create-build-initiated.md | 19 +---------------- .../events/data-types/entityobject.md | 20 ++++++++++++++++++ .../events/data-types/fullnameobject.md | 20 ++++++++++++++++++ .../events/data-types/originatorobject.md | 20 ++++++++++++++++++ .../events/display-name-filtered.md | 16 +------------- .../events/enabled-for-title.md | 19 +---------------- .../api-references/events/entity-created.md | 16 +------------- .../events/entity-executed-cloud-script.md | 16 +------------- .../api-references/events/entity-files-set.md | 16 +------------- .../events/entity-language-updated.md | 16 +------------- .../api-references/events/entity-logged-in.md | 16 +------------- .../events/entity-objects-set.md | 20 ++---------------- ...ntity-rank-on-leaderboard-version-ended.md | 16 +------------- ...ntity-virtual-currency-balances-changed.md | 16 +------------- .../events/game-asset-deleted.md | 19 +---------------- .../api-references/events/group-created.md | 16 +------------- .../api-references/events/group-deleted.md | 16 +------------- .../events/group-members-added.md | 16 +------------- .../events/group-members-removed.md | 16 +------------- .../events/group-role-created.md | 16 +------------- .../events/group-role-deleted.md | 16 +------------- .../events/group-role-members-added.md | 16 +------------- .../events/group-role-members-removed.md | 16 +------------- .../events/group-role-updated.md | 16 +------------- .../api-references/events/group-updated.md | 16 +------------- .../api-references/events/item-created.md | 16 +------------- .../api-references/events/item-deleted.md | 16 +------------- .../events/item-moderation-state-changed.md | 16 +------------- .../events/item-publish-requested.md | 16 +------------- .../api-references/events/item-reported.md | 17 +-------------- .../api-references/events/item-updated.md | 16 +------------- .../api-references/events/items-added.md | 16 +------------- .../api-references/events/items-deleted.md | 16 +------------- .../api-references/events/items-purchased.md | 16 +------------- .../api-references/events/items-redeemed.md | 16 +------------- .../api-references/events/items-subtracted.md | 16 +------------- .../events/items-transferred.md | 16 +------------- .../api-references/events/items-updated.md | 16 +------------- .../events/leaderboard-version-ended.md | 16 +------------- .../marketplace-transaction-redeemed.md | 20 ++---------------- .../events/matchmaking-match-found.md | 16 +------------- .../events/matchmaking-ticket-completed.md | 16 +------------- .../matchmaking-user-ticket-completed.md | 16 +------------- .../events/matchmaking-user-ticket-invite.md | 16 +------------- .../events/monitoring-output-saved.md | 19 +---------------- .../events/player-action-executed.md | 16 +------------- .../events/player-ad-activity-valued.md | 16 +------------- .../events/player-ad-campaign-attribution.md | 16 +------------- .../api-references/events/player-ad-closed.md | 16 +------------- .../api-references/events/player-ad-ended.md | 16 +------------- .../api-references/events/player-ad-opened.md | 16 +------------- .../events/player-ad-rewarded.md | 16 +------------- .../events/player-ad-started.md | 16 +------------- .../events/player-added-title.md | 16 +------------- .../api-references/events/player-banned.md | 16 +------------- .../events/player-changed-avatar.md | 16 +------------- .../events/player-completed-password-reset.md | 16 +------------- .../events/player-consumed-item.md | 16 +------------- .../api-references/events/player-created.md | 16 +------------- .../events/player-data-exported.md | 16 +------------- .../events/player-device-info.md | 16 +------------- .../events/player-display-name-filtered.md | 16 +------------- .../events/player-displayname-changed.md | 16 +------------- .../events/player-executed-cloudscript.md | 16 +------------- .../events/player-inventory-item-added.md | 16 +------------- .../events/player-linked-account.md | 16 +------------- .../api-references/events/player-logged-in.md | 16 +------------- .../events/player-paid-for-purchase.md | 16 +------------- .../events/player-password-reset-link-sent.md | 16 +------------- .../player-photon-session-authenticated.md | 16 +------------- .../player-ranked-on-leaderboard-version.md | 16 +------------- .../events/player-realmoney-purchase.md | 16 +------------- .../events/player-receipt-validation.md | 16 +------------- .../events/player-redeemed-coupon.md | 16 +------------- .../player-registered-push-notifications.md | 16 +------------- .../events/player-removed-title.md | 16 +------------- .../events/player-reported-as-abusive.md | 16 +------------- .../events/player-set-profile-property.md | 16 +------------- .../events/player-started-purchase.md | 16 +------------- .../events/player-statistic-changed.md | 16 +------------- .../events/player-statistic-deleted.md | 16 +------------- .../api-references/events/player-tag-added.md | 16 +------------- .../events/player-tag-removed.md | 16 +------------- ...r-triggered-action-executed-cloudscript.md | 16 +------------- .../events/player-unlinked-account.md | 16 +------------- .../events/player-updated-contact-email.md | 16 +------------- .../events/player-vc-item-purchased.md | 16 +------------- .../events/player-verified-contact-email.md | 16 +------------- ...player-virtual-currency-balance-changed.md | 16 +------------- .../api-references/events/review-reported.md | 17 +-------------- .../events/reviews-takedown-requested.md | 16 +------------- .../api-references/events/secret-added.md | 19 +---------------- .../api-references/events/secret-deleted.md | 19 +---------------- .../api-references/events/sent-email.md | 16 +------------- .../events/sent-push-notification.md | 16 +------------- .../api-references/events/server-requested.md | 21 +++---------------- .../events/server-state-changed.md | 21 +++---------------- .../events/statistic-updated.md | 16 +------------- .../api-references/events/studio-created.md | 16 +------------- .../events/studio-tier-updated.md | 16 +------------- .../events/studio-user-added.md | 16 +------------- .../events/studio-user-invited.md | 16 +------------- .../events/studio-user-removed.md | 16 +------------- .../events/tenancy-connector-onboard.md | 16 +------------- .../events/title-aborted-task.md | 16 +------------- .../events/title-added-cloudscript.md | 16 +------------- .../events/title-api-settings-changed.md | 16 +------------- .../events/title-catalog-updated.md | 16 +------------- .../events/title-client-rate-limited-alert.md | 16 +------------- .../events/title-completed-task.md | 16 +------------- .../events/title-created-task.md | 16 +------------- .../events/title-deleted-master-player.md | 16 +------------- .../events/title-deleted-task.md | 16 +------------- .../api-references/events/title-deleted.md | 16 +------------- .../events/title-exceeded-limit.md | 18 ++-------------- .../events/title-high-error-rate-alert.md | 16 +------------- .../title-initiated-player-password-reset.md | 16 +------------- .../events/title-limit-changed.md | 16 +------------- .../events/title-news-updated.md | 16 +------------- .../events/title-permission-policy-changed.md | 16 +------------- .../title-profile-view-constraints-changed.md | 16 +------------- .../events/title-published-cloudscript.md | 16 +------------- .../events/title-queue-config-updated.md | 16 +------------- .../events/title-requested-limit-change.md | 16 +------------- .../events/title-saved-survey.md | 16 +------------- .../title-scheduled-cloudscript-executed.md | 16 +------------- .../events/title-secret-key-changed.md | 16 +------------- .../events/title-started-task.md | 16 +------------- .../events/title-statistic-version-changed.md | 16 +------------- .../events/title-store-updated.md | 16 +------------- .../events/title-updated-task.md | 16 +------------- .../api-references/events/vm-assigned.md | 19 +---------------- .../events/vm-game-certificates-deployed.md | 20 +----------------- .../events/vm-remote-user-created.md | 19 +---------------- .../events/vm-remote-user-deleted.md | 19 +---------------- .../api-references/events/vm-state-change.md | 19 +---------------- .../events/vm-unassignment-started.md | 19 +---------------- .../api-references/events/vm-unhealthy.md | 19 +---------------- .../includes/_common-properties-eventsv1.md | 12 +++++++++++ .../includes/_common-properties-eventsv2.md | 12 +++++++++++ playfab-docs/sdks/toc.yml | 2 +- 161 files changed, 247 insertions(+), 2412 deletions(-) create mode 100644 playfab-docs/api-references/events/data-types/entityobject.md create mode 100644 playfab-docs/api-references/events/data-types/fullnameobject.md create mode 100644 playfab-docs/api-references/events/data-types/originatorobject.md create mode 100644 playfab-docs/includes/_common-properties-eventsv1.md create mode 100644 playfab-docs/includes/_common-properties-eventsv2.md diff --git a/playfab-docs/api-references/events/auth-token-validated.md b/playfab-docs/api-references/events/auth-token-validated.md index 0e3c0b93c..ef68c556a 100644 --- a/playfab-docs/api-references/events/auth-token-validated.md +++ b/playfab-docs/api-references/events/auth-token-validated.md @@ -24,18 +24,4 @@ This event is triggered when an email confirmation link is clicked. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/build-alias-created.md b/playfab-docs/api-references/events/build-alias-created.md index 4b1c0ab8d..aa9694760 100644 --- a/playfab-docs/api-references/events/build-alias-created.md +++ b/playfab-docs/api-references/events/build-alias-created.md @@ -19,26 +19,8 @@ This event is triggered when a multiplayer server build alias is created. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[BuildAliasCreatedEventPayload](data-types/buildaliascreatedeventpayload.md)|The multiplayer server build alias created event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| - +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-alias-deleted.md b/playfab-docs/api-references/events/build-alias-deleted.md index 5a96b8b54..babf5b7f0 100644 --- a/playfab-docs/api-references/events/build-alias-deleted.md +++ b/playfab-docs/api-references/events/build-alias-deleted.md @@ -19,25 +19,8 @@ This event is triggered when a multiplayer server build alias is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[BuildAliasDeletedEventPayload](data-types/buildaliasdeletedeventpayload.md)|The multiplayer server build alias deleted event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-alias-updated.md b/playfab-docs/api-references/events/build-alias-updated.md index ae3275574..69d72c93b 100644 --- a/playfab-docs/api-references/events/build-alias-updated.md +++ b/playfab-docs/api-references/events/build-alias-updated.md @@ -19,26 +19,9 @@ This event is triggered when a multiplayer server build alias is updated. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[BuildAliasUpdatedEventPayload](data-types/buildaliasupdatedeventpayload.md)|The multiplayer server build alias updated event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-deleted.md b/playfab-docs/api-references/events/build-deleted.md index 1a1ede519..fdbe4f5a7 100644 --- a/playfab-docs/api-references/events/build-deleted.md +++ b/playfab-docs/api-references/events/build-deleted.md @@ -19,27 +19,10 @@ This event is triggered when a multiplayer server build is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[BuildDeletedEventPayload](data-types/builddeletedeventpayload.md)|The multiplayer server build deleted event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-region-status-changed.md b/playfab-docs/api-references/events/build-region-status-changed.md index 55c945293..0471bdc63 100644 --- a/playfab-docs/api-references/events/build-region-status-changed.md +++ b/playfab-docs/api-references/events/build-region-status-changed.md @@ -19,27 +19,10 @@ This event is triggered when a multiplayer server's build region status is chang |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[BuildRegionStatusChangedEventPayload](data-types/buildregionstatuschangedeventpayload.md)|The multiplayer server build region status changed event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-region-updated.md b/playfab-docs/api-references/events/build-region-updated.md index 56dbe2c75..44ca49a79 100644 --- a/playfab-docs/api-references/events/build-region-updated.md +++ b/playfab-docs/api-references/events/build-region-updated.md @@ -19,26 +19,9 @@ This event is triggered when a multiplayer server build region is updated. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[BuildRegionUpdatedEventPayload](data-types/buildregionupdatedeventpayload.md)|The multiplayer server build region updated event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-region-utilization.md b/playfab-docs/api-references/events/build-region-utilization.md index 2c71f7e1e..0a87a9e95 100644 --- a/playfab-docs/api-references/events/build-region-utilization.md +++ b/playfab-docs/api-references/events/build-region-utilization.md @@ -19,26 +19,9 @@ This event is triggered to display the utilization of servers for a build in eac |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[BuildRegionUtilizationEventPayload](data-types/buildregionutilizationeventpayload.md)|The multiplayer server build region utilization event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/certificate-deleted.md b/playfab-docs/api-references/events/certificate-deleted.md index 421b229df..5f4987aa9 100644 --- a/playfab-docs/api-references/events/certificate-deleted.md +++ b/playfab-docs/api-references/events/certificate-deleted.md @@ -19,25 +19,8 @@ This event is triggered when a multiplayer server certificate is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[CertificateDeletedEventPayload](data-types/certificatedeletedeventpayload.md)|The multiplayer server certificate deleted event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/certificate-uploaded.md b/playfab-docs/api-references/events/certificate-uploaded.md index d54bc860a..6a334d05b 100644 --- a/playfab-docs/api-references/events/certificate-uploaded.md +++ b/playfab-docs/api-references/events/certificate-uploaded.md @@ -19,26 +19,9 @@ This event is triggered when a multiplayer server certificate is uploaded. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[CertificateUploadedEventPayload](data-types/certificateuploadedeventpayload.md)|The multiplayer server certificate uploaded event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/character-consumed-item.md b/playfab-docs/api-references/events/character-consumed-item.md index b2ad18335..88ee4d266 100644 --- a/playfab-docs/api-references/events/character-consumed-item.md +++ b/playfab-docs/api-references/events/character-consumed-item.md @@ -28,18 +28,4 @@ This event is triggered when a character consumes an item from their inventory. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-created.md b/playfab-docs/api-references/events/character-created.md index f47f302a0..04fdef752 100644 --- a/playfab-docs/api-references/events/character-created.md +++ b/playfab-docs/api-references/events/character-created.md @@ -25,18 +25,4 @@ This event is triggered when a character is created for the first time. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-inventory-item-added.md b/playfab-docs/api-references/events/character-inventory-item-added.md index 87e2edbe4..cd36929d2 100644 --- a/playfab-docs/api-references/events/character-inventory-item-added.md +++ b/playfab-docs/api-references/events/character-inventory-item-added.md @@ -33,18 +33,4 @@ This event is triggered when an item is granted to a character. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-statistic-changed.md b/playfab-docs/api-references/events/character-statistic-changed.md index 6d36ea590..3a8fe5345 100644 --- a/playfab-docs/api-references/events/character-statistic-changed.md +++ b/playfab-docs/api-references/events/character-statistic-changed.md @@ -27,18 +27,4 @@ This event is triggered when a character statistic is changed. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-statistic-deleted.md b/playfab-docs/api-references/events/character-statistic-deleted.md index a971bb771..31c7b4b80 100644 --- a/playfab-docs/api-references/events/character-statistic-deleted.md +++ b/playfab-docs/api-references/events/character-statistic-deleted.md @@ -25,18 +25,4 @@ This event is triggered when a character statistic is deleted. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-vc-item-purchased.md b/playfab-docs/api-references/events/character-vc-item-purchased.md index f145fbbc0..fd58520c1 100644 --- a/playfab-docs/api-references/events/character-vc-item-purchased.md +++ b/playfab-docs/api-references/events/character-vc-item-purchased.md @@ -30,18 +30,4 @@ This event is triggered when the character makes a purchase using virtual curren ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-virtual-currency-balance-changed.md b/playfab-docs/api-references/events/character-virtual-currency-balance-changed.md index e94de6bc3..26922799c 100644 --- a/playfab-docs/api-references/events/character-virtual-currency-balance-changed.md +++ b/playfab-docs/api-references/events/character-virtual-currency-balance-changed.md @@ -27,18 +27,4 @@ This event is triggered when a character's virtual currency balance changes. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/client-focus-change.md b/playfab-docs/api-references/events/client-focus-change.md index 83f0f472f..f6b179762 100644 --- a/playfab-docs/api-references/events/client-focus-change.md +++ b/playfab-docs/api-references/events/client-focus-change.md @@ -26,18 +26,4 @@ This event is triggered every time the application enters or exits focus on the ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/client-session-start.md b/playfab-docs/api-references/events/client-session-start.md index c459a1cb7..04046abf0 100644 --- a/playfab-docs/api-references/events/client-session-start.md +++ b/playfab-docs/api-references/events/client-session-start.md @@ -26,18 +26,4 @@ Properties ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/crash-detected.md b/playfab-docs/api-references/events/crash-detected.md index dddec0188..9f3e6a6c7 100644 --- a/playfab-docs/api-references/events/crash-detected.md +++ b/playfab-docs/api-references/events/crash-detected.md @@ -19,26 +19,9 @@ This event triggered when a crash dump is found on a terminating server. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[CrashDetectedEventPayload](data-types/crashdetectedeventpayload.md)|The multiplayer server crash detected event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/create-build-initiated.md b/playfab-docs/api-references/events/create-build-initiated.md index 92253f0d0..0eeba5338 100644 --- a/playfab-docs/api-references/events/create-build-initiated.md +++ b/playfab-docs/api-references/events/create-build-initiated.md @@ -19,26 +19,9 @@ This event is triggered when a multiplayer server build is initiated. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[CreateBuildInitiatedEventPayload](data-types/createbuildinitiatedeventpayload.md)|The multiplayer server create build initiated event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/data-types/entityobject.md b/playfab-docs/api-references/events/data-types/entityobject.md new file mode 100644 index 000000000..3367f81c2 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/entityobject.md @@ -0,0 +1,20 @@ +--- +title: EntityObject +author: valexao +description: EntityObject data type. +ms.author: vorelien +ms.date: 01/21/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# EntityObject + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|Unique ID of the entity.| +|Type|String|One of the [available built-in entity types](../../../live-service-management/game-configuration/entities/available-built-in-entity-types.md).| \ No newline at end of file diff --git a/playfab-docs/api-references/events/data-types/fullnameobject.md b/playfab-docs/api-references/events/data-types/fullnameobject.md new file mode 100644 index 000000000..15824cd78 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/fullnameobject.md @@ -0,0 +1,20 @@ +--- +title: FullNameObject +author: valexao +description: FullNameObject data type. +ms.author: vorelien +ms.date: 01/21/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# FullNameObject + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| \ No newline at end of file diff --git a/playfab-docs/api-references/events/data-types/originatorobject.md b/playfab-docs/api-references/events/data-types/originatorobject.md new file mode 100644 index 000000000..40a3560c7 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/originatorobject.md @@ -0,0 +1,20 @@ +--- +title: OriginatorObject +author: valexao +description: OriginatorObject data type. +ms.author: vorelien +ms.date: 01/21/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# OriginatorObject + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|Source of the Playstream event - will be PlayFab if the event originated from us.| +|Type|String|The type of the source of this event. List of possible values found here: [SourceType](../data-types/sourcetype.md)| \ No newline at end of file diff --git a/playfab-docs/api-references/events/display-name-filtered.md b/playfab-docs/api-references/events/display-name-filtered.md index 598a70cad..4bfc95247 100644 --- a/playfab-docs/api-references/events/display-name-filtered.md +++ b/playfab-docs/api-references/events/display-name-filtered.md @@ -23,18 +23,4 @@ This event is triggered when a display name is filtered by community sift. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/enabled-for-title.md b/playfab-docs/api-references/events/enabled-for-title.md index 55b2b7094..5cd64b4aa 100644 --- a/playfab-docs/api-references/events/enabled-for-title.md +++ b/playfab-docs/api-references/events/enabled-for-title.md @@ -19,25 +19,8 @@ This event is triggered when a title enables PlayFab multiplayer servers. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/entity-created.md b/playfab-docs/api-references/events/entity-created.md index e31748aeb..9a0a3e057 100644 --- a/playfab-docs/api-references/events/entity-created.md +++ b/playfab-docs/api-references/events/entity-created.md @@ -23,18 +23,4 @@ This event is triggered when an entity is created. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/entity-executed-cloud-script.md b/playfab-docs/api-references/events/entity-executed-cloud-script.md index 7af06cdc4..fa5f5d896 100644 --- a/playfab-docs/api-references/events/entity-executed-cloud-script.md +++ b/playfab-docs/api-references/events/entity-executed-cloud-script.md @@ -25,18 +25,4 @@ This event is optionally triggered when a CloudScript function is executed by ca ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/entity-files-set.md b/playfab-docs/api-references/events/entity-files-set.md index 19fe45733..0301e68e0 100644 --- a/playfab-docs/api-references/events/entity-files-set.md +++ b/playfab-docs/api-references/events/entity-files-set.md @@ -24,18 +24,4 @@ This event is triggered when files are attached to an entity. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/entity-language-updated.md b/playfab-docs/api-references/events/entity-language-updated.md index 0cc84461b..0b985283b 100644 --- a/playfab-docs/api-references/events/entity-language-updated.md +++ b/playfab-docs/api-references/events/entity-language-updated.md @@ -24,19 +24,5 @@ This event is triggered when the language associated with an entity is changed. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/entity-logged-in.md b/playfab-docs/api-references/events/entity-logged-in.md index 3c702c600..ffee1d260 100644 --- a/playfab-docs/api-references/events/entity-logged-in.md +++ b/playfab-docs/api-references/events/entity-logged-in.md @@ -23,20 +23,6 @@ This event is triggered when an entity has logged in. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/entity-objects-set.md b/playfab-docs/api-references/events/entity-objects-set.md index a72ef17b4..d40e4b3a9 100644 --- a/playfab-docs/api-references/events/entity-objects-set.md +++ b/playfab-docs/api-references/events/entity-objects-set.md @@ -19,25 +19,9 @@ This event is triggered when objects are attached to an entity. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| |Objects|[ObjectSet](data-types/objectset.md)|Objects that were updated| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| - - +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/entity-rank-on-leaderboard-version-ended.md b/playfab-docs/api-references/events/entity-rank-on-leaderboard-version-ended.md index c6f922269..367c5ff4a 100644 --- a/playfab-docs/api-references/events/entity-rank-on-leaderboard-version-ended.md +++ b/playfab-docs/api-references/events/entity-rank-on-leaderboard-version-ended.md @@ -26,18 +26,4 @@ This event is triggered when a leaderboard version is reset to a new version for ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"items_purchased"| -|EventNamespace|String|"playfab.inventory"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/entity-virtual-currency-balances-changed.md b/playfab-docs/api-references/events/entity-virtual-currency-balances-changed.md index d4260dfe8..039f7a733 100644 --- a/playfab-docs/api-references/events/entity-virtual-currency-balances-changed.md +++ b/playfab-docs/api-references/events/entity-virtual-currency-balances-changed.md @@ -27,18 +27,4 @@ This event is triggered when an entity's virtual currency balance changes. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| - +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/game-asset-deleted.md b/playfab-docs/api-references/events/game-asset-deleted.md index f966cb5b4..09bd007f6 100644 --- a/playfab-docs/api-references/events/game-asset-deleted.md +++ b/playfab-docs/api-references/events/game-asset-deleted.md @@ -18,26 +18,9 @@ This event is triggered when a multiplayer server game asset is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[GameAssetDeletedEventPayload](data-types/gameassetdeletedeventpayload.md)|The multiplayer server game asset deleted event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/group-created.md b/playfab-docs/api-references/events/group-created.md index 96ee40393..a61006e88 100644 --- a/playfab-docs/api-references/events/group-created.md +++ b/playfab-docs/api-references/events/group-created.md @@ -26,19 +26,5 @@ This event is triggered when an entity group is created. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-deleted.md b/playfab-docs/api-references/events/group-deleted.md index 1cace51e0..b37b002ac 100644 --- a/playfab-docs/api-references/events/group-deleted.md +++ b/playfab-docs/api-references/events/group-deleted.md @@ -26,19 +26,5 @@ This event is triggered when an entity group is deleted. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-members-added.md b/playfab-docs/api-references/events/group-members-added.md index 294ea9c04..324a667df 100644 --- a/playfab-docs/api-references/events/group-members-added.md +++ b/playfab-docs/api-references/events/group-members-added.md @@ -27,19 +27,5 @@ This event is triggered when a member is added to an entity group. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-members-removed.md b/playfab-docs/api-references/events/group-members-removed.md index 8d1d8f6d9..8b4e06fc4 100644 --- a/playfab-docs/api-references/events/group-members-removed.md +++ b/playfab-docs/api-references/events/group-members-removed.md @@ -25,18 +25,4 @@ This event is triggered when a member is removed from an entity group ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-created.md b/playfab-docs/api-references/events/group-role-created.md index b6f1ebf65..cfe9c5dfc 100644 --- a/playfab-docs/api-references/events/group-role-created.md +++ b/playfab-docs/api-references/events/group-role-created.md @@ -28,21 +28,7 @@ This event is triggered when a role is created for a group. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-deleted.md b/playfab-docs/api-references/events/group-role-deleted.md index 4c3791c30..9733298b1 100644 --- a/playfab-docs/api-references/events/group-role-deleted.md +++ b/playfab-docs/api-references/events/group-role-deleted.md @@ -28,21 +28,7 @@ This event is triggered when a role is deleted from a group. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-members-added.md b/playfab-docs/api-references/events/group-role-members-added.md index 4b8347620..8d785c153 100644 --- a/playfab-docs/api-references/events/group-role-members-added.md +++ b/playfab-docs/api-references/events/group-role-members-added.md @@ -27,21 +27,7 @@ This event is triggered when a list of entities are added to a role within a gro ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-members-removed.md b/playfab-docs/api-references/events/group-role-members-removed.md index 6207f4561..e38badb45 100644 --- a/playfab-docs/api-references/events/group-role-members-removed.md +++ b/playfab-docs/api-references/events/group-role-members-removed.md @@ -27,21 +27,7 @@ This event is triggered when a list of entities are removed from a role within a ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-updated.md b/playfab-docs/api-references/events/group-role-updated.md index bcc168f28..b3b4a9361 100644 --- a/playfab-docs/api-references/events/group-role-updated.md +++ b/playfab-docs/api-references/events/group-role-updated.md @@ -30,20 +30,6 @@ This event is triggered when a role is updated within a group. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-updated.md b/playfab-docs/api-references/events/group-updated.md index ac9b3ed90..2bc0ec7ca 100644 --- a/playfab-docs/api-references/events/group-updated.md +++ b/playfab-docs/api-references/events/group-updated.md @@ -28,20 +28,6 @@ This event is triggered when an entity group is updated. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/item-created.md b/playfab-docs/api-references/events/item-created.md index 8e4f50bf2..36ef0832f 100644 --- a/playfab-docs/api-references/events/item-created.md +++ b/playfab-docs/api-references/events/item-created.md @@ -23,18 +23,4 @@ This event is triggered when an item is created. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"item_created"| -|EventNamespace|String|"playfab.catalog"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/item-deleted.md b/playfab-docs/api-references/events/item-deleted.md index c41bfa6a2..a70f683bd 100644 --- a/playfab-docs/api-references/events/item-deleted.md +++ b/playfab-docs/api-references/events/item-deleted.md @@ -23,18 +23,4 @@ This event is triggered when an item is deleted. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"item_deleted"| -|EventNamespace|String|"playfab.catalog"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/item-moderation-state-changed.md b/playfab-docs/api-references/events/item-moderation-state-changed.md index 2afe63c5a..8ad7dc5ab 100644 --- a/playfab-docs/api-references/events/item-moderation-state-changed.md +++ b/playfab-docs/api-references/events/item-moderation-state-changed.md @@ -24,18 +24,4 @@ This event is triggered when an item moderation state is changed. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"item_moderation_state_changed"| -|EventNamespace|String|"playfab.catalog"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/item-publish-requested.md b/playfab-docs/api-references/events/item-publish-requested.md index ccbbbccda..1e4374fb3 100644 --- a/playfab-docs/api-references/events/item-publish-requested.md +++ b/playfab-docs/api-references/events/item-publish-requested.md @@ -23,18 +23,4 @@ This event is triggered when an publishing is started. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"item_publish_requested"| -|EventNamespace|String|"playfab.catalog"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/item-reported.md b/playfab-docs/api-references/events/item-reported.md index 5fc0b6fcc..74059702d 100644 --- a/playfab-docs/api-references/events/item-reported.md +++ b/playfab-docs/api-references/events/item-reported.md @@ -24,21 +24,6 @@ This event is triggered when an item is reported. |ConcernCategory|String|The category for which this item was reported.| |Reason|String|The reason for which this item was reported.| - ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"item_reported"| -|EventNamespace|String|"playfab.catalog"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/item-updated.md b/playfab-docs/api-references/events/item-updated.md index a4fe04de2..36f7bd178 100644 --- a/playfab-docs/api-references/events/item-updated.md +++ b/playfab-docs/api-references/events/item-updated.md @@ -23,18 +23,4 @@ This event is triggered when an item is updated. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"item_updated"| -|EventNamespace|String|"playfab.catalog"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-added.md b/playfab-docs/api-references/events/items-added.md index 9b943c2d9..de1ca1b1c 100644 --- a/playfab-docs/api-references/events/items-added.md +++ b/playfab-docs/api-references/events/items-added.md @@ -29,18 +29,4 @@ Event raised when items have been added to an inventory. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"items_added"| -|EventNamespace|String|"playfab.inventory"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/items-deleted.md b/playfab-docs/api-references/events/items-deleted.md index 2499d290a..37e93c148 100644 --- a/playfab-docs/api-references/events/items-deleted.md +++ b/playfab-docs/api-references/events/items-deleted.md @@ -26,18 +26,4 @@ Event raised when items have been deleted from an inventory. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"items_deleted"| -|EventNamespace|String|"playfab.inventory"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/items-purchased.md b/playfab-docs/api-references/events/items-purchased.md index 4cc777fd5..fa5a2e9e1 100644 --- a/playfab-docs/api-references/events/items-purchased.md +++ b/playfab-docs/api-references/events/items-purchased.md @@ -31,18 +31,4 @@ Event raised when items have been purchased from an inventory. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"items_purchased"| -|EventNamespace|String|"playfab.inventory"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-redeemed.md b/playfab-docs/api-references/events/items-redeemed.md index a0e446086..129d96071 100644 --- a/playfab-docs/api-references/events/items-redeemed.md +++ b/playfab-docs/api-references/events/items-redeemed.md @@ -31,18 +31,4 @@ Event raised when items have been redeemed to an inventory. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"items_redeemed"| -|EventNamespace|String|"playfab.inventory"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-subtracted.md b/playfab-docs/api-references/events/items-subtracted.md index 4413b7eb9..4527c8821 100644 --- a/playfab-docs/api-references/events/items-subtracted.md +++ b/playfab-docs/api-references/events/items-subtracted.md @@ -29,18 +29,4 @@ Event raised when items have been subtracted from an inventory. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"items_subtracted"| -|EventNamespace|String|"playfab.inventory"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-transferred.md b/playfab-docs/api-references/events/items-transferred.md index 886e05720..6ca8f8e5f 100644 --- a/playfab-docs/api-references/events/items-transferred.md +++ b/playfab-docs/api-references/events/items-transferred.md @@ -33,18 +33,4 @@ Event raised when items have been transferred to or from an inventory. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"items_transferred"| -|EventNamespace|String|"playfab.inventory"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-updated.md b/playfab-docs/api-references/events/items-updated.md index ea21edc3c..42d035b47 100644 --- a/playfab-docs/api-references/events/items-updated.md +++ b/playfab-docs/api-references/events/items-updated.md @@ -28,18 +28,4 @@ Event raised when items have been updated in an inventory. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"items_updated"| -|EventNamespace|String|"playfab.inventory"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/leaderboard-version-ended.md b/playfab-docs/api-references/events/leaderboard-version-ended.md index 5f6f6d3ac..e661453da 100644 --- a/playfab-docs/api-references/events/leaderboard-version-ended.md +++ b/playfab-docs/api-references/events/leaderboard-version-ended.md @@ -24,18 +24,4 @@ This event is triggered when a leaderboard version is reset to a new version for ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"items_purchased"| -|EventNamespace|String|"playfab.inventory"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/marketplace-transaction-redeemed.md b/playfab-docs/api-references/events/marketplace-transaction-redeemed.md index 5690fefc9..ae32bd1de 100644 --- a/playfab-docs/api-references/events/marketplace-transaction-redeemed.md +++ b/playfab-docs/api-references/events/marketplace-transaction-redeemed.md @@ -27,22 +27,6 @@ This event is triggered when a bundle or subscription has been redeemed to an in |ItemType|String|The type of the catalog item that was redeemed.| |RealMoneyPrices|Dictionary|The multi-currency unit price, in real money, of the item that was redeemed. The property is a dictionary where the key is the three-letter currency code as defined in ISO 4217, and the value is the currency amount in the smallest unit (for example, cents, pence) in accordance with ISO 4217. Only United States Dollar (USD) is currently supported. Example: If the product price in USD is $1.39, the dictionary entry would be: ["USD"] = 139;| -## Common properties - -All PlayStream events are formatted as JSON objects and share the following common properties. - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (such as title and player) to which this event applies.| -|EntityType|String|The type of entity (such as player and title) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like **com.mygame.guild**) as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: **com.myprogram.ads**| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| - +## Common Properties +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/matchmaking-match-found.md b/playfab-docs/api-references/events/matchmaking-match-found.md index b4c560961..9f459cc97 100644 --- a/playfab-docs/api-references/events/matchmaking-match-found.md +++ b/playfab-docs/api-references/events/matchmaking-match-found.md @@ -24,20 +24,6 @@ This event is triggered when a group of tickets are matched together. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/matchmaking-ticket-completed.md b/playfab-docs/api-references/events/matchmaking-ticket-completed.md index 628961d66..fe09133df 100644 --- a/playfab-docs/api-references/events/matchmaking-ticket-completed.md +++ b/playfab-docs/api-references/events/matchmaking-ticket-completed.md @@ -24,18 +24,4 @@ This event is triggered when a matchmaking ticket reaches a completion state. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/matchmaking-user-ticket-completed.md b/playfab-docs/api-references/events/matchmaking-user-ticket-completed.md index 0a924fdb6..ed9ca6a95 100644 --- a/playfab-docs/api-references/events/matchmaking-user-ticket-completed.md +++ b/playfab-docs/api-references/events/matchmaking-user-ticket-completed.md @@ -24,20 +24,6 @@ This event is triggered when a matchmaking ticket reaches a completion state. Th ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/matchmaking-user-ticket-invite.md b/playfab-docs/api-references/events/matchmaking-user-ticket-invite.md index b1c10ebcc..bdade1cd4 100644 --- a/playfab-docs/api-references/events/matchmaking-user-ticket-invite.md +++ b/playfab-docs/api-references/events/matchmaking-user-ticket-invite.md @@ -24,20 +24,6 @@ This event is triggered when a ticket with an invited user is created. The event ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/monitoring-output-saved.md b/playfab-docs/api-references/events/monitoring-output-saved.md index c1ac05abc..75c5680d2 100644 --- a/playfab-docs/api-references/events/monitoring-output-saved.md +++ b/playfab-docs/api-references/events/monitoring-output-saved.md @@ -19,26 +19,9 @@ This event is triggered when the output of a monitoring application has been sav |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[MonitoringOutputSavedEventPayload](data-types/monitoringoutputsavedeventpayload.md)|The multiplayer server monitoring output saved event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/player-action-executed.md b/playfab-docs/api-references/events/player-action-executed.md index bb22dc707..3f3b624b9 100644 --- a/playfab-docs/api-references/events/player-action-executed.md +++ b/playfab-docs/api-references/events/player-action-executed.md @@ -30,18 +30,4 @@ Properties ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-activity-valued.md b/playfab-docs/api-references/events/player-ad-activity-valued.md index ce0e6d6e2..a626afc31 100644 --- a/playfab-docs/api-references/events/player-ad-activity-valued.md +++ b/playfab-docs/api-references/events/player-ad-activity-valued.md @@ -28,18 +28,4 @@ Event triggered when reported value of ad view is recorded ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-campaign-attribution.md b/playfab-docs/api-references/events/player-ad-campaign-attribution.md index 46972b2c8..f65135bbc 100644 --- a/playfab-docs/api-references/events/player-ad-campaign-attribution.md +++ b/playfab-docs/api-references/events/player-ad-campaign-attribution.md @@ -23,18 +23,4 @@ This event is triggered by an attribution tracking Add-on when a player is match ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-closed.md b/playfab-docs/api-references/events/player-ad-closed.md index 626aff6d9..11e092b58 100644 --- a/playfab-docs/api-references/events/player-ad-closed.md +++ b/playfab-docs/api-references/events/player-ad-closed.md @@ -27,18 +27,4 @@ This event is triggered when a player closes an ad. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-ended.md b/playfab-docs/api-references/events/player-ad-ended.md index 75b605939..2a5954134 100644 --- a/playfab-docs/api-references/events/player-ad-ended.md +++ b/playfab-docs/api-references/events/player-ad-ended.md @@ -27,18 +27,4 @@ This event is triggered when a player finishes an ad. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-opened.md b/playfab-docs/api-references/events/player-ad-opened.md index d7d920f63..4ee11dfb8 100644 --- a/playfab-docs/api-references/events/player-ad-opened.md +++ b/playfab-docs/api-references/events/player-ad-opened.md @@ -27,18 +27,4 @@ This event is triggered when a player opens an ad. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-rewarded.md b/playfab-docs/api-references/events/player-ad-rewarded.md index 453325d00..9e707ebbd 100644 --- a/playfab-docs/api-references/events/player-ad-rewarded.md +++ b/playfab-docs/api-references/events/player-ad-rewarded.md @@ -29,18 +29,4 @@ This event is triggered when a player recieves an ad reward. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-started.md b/playfab-docs/api-references/events/player-ad-started.md index add24300e..28b48f5a5 100644 --- a/playfab-docs/api-references/events/player-ad-started.md +++ b/playfab-docs/api-references/events/player-ad-started.md @@ -27,18 +27,4 @@ This event is triggered when a player starts an ad. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-added-title.md b/playfab-docs/api-references/events/player-added-title.md index f128034b1..6b97edbe1 100644 --- a/playfab-docs/api-references/events/player-added-title.md +++ b/playfab-docs/api-references/events/player-added-title.md @@ -25,18 +25,4 @@ This event is triggered when a player creates a new account for a title. Note: t ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-banned.md b/playfab-docs/api-references/events/player-banned.md index 40f8b69e1..45a0583a0 100644 --- a/playfab-docs/api-references/events/player-banned.md +++ b/playfab-docs/api-references/events/player-banned.md @@ -26,18 +26,4 @@ This event is triggered when a player is banned. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-changed-avatar.md b/playfab-docs/api-references/events/player-changed-avatar.md index 036e59076..3cea56e7a 100644 --- a/playfab-docs/api-references/events/player-changed-avatar.md +++ b/playfab-docs/api-references/events/player-changed-avatar.md @@ -24,18 +24,4 @@ This event is triggered when a player's avatar URL is changed. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-completed-password-reset.md b/playfab-docs/api-references/events/player-completed-password-reset.md index 83d212481..1146cdfbf 100644 --- a/playfab-docs/api-references/events/player-completed-password-reset.md +++ b/playfab-docs/api-references/events/player-completed-password-reset.md @@ -30,18 +30,4 @@ This event is triggered when a player completes the password reset process by vi ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-consumed-item.md b/playfab-docs/api-references/events/player-consumed-item.md index b3aa4fcda..9198c769e 100644 --- a/playfab-docs/api-references/events/player-consumed-item.md +++ b/playfab-docs/api-references/events/player-consumed-item.md @@ -27,18 +27,4 @@ This event is triggered when a player consumes an item from their inventory. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-created.md b/playfab-docs/api-references/events/player-created.md index 83d7d4197..286dbb347 100644 --- a/playfab-docs/api-references/events/player-created.md +++ b/playfab-docs/api-references/events/player-created.md @@ -24,18 +24,4 @@ This event is triggered when a player account is created for the first time. Not ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-data-exported.md b/playfab-docs/api-references/events/player-data-exported.md index 0250cc535..377a7733f 100644 --- a/playfab-docs/api-references/events/player-data-exported.md +++ b/playfab-docs/api-references/events/player-data-exported.md @@ -25,18 +25,4 @@ This event is triggered when a player's data is exported. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-device-info.md b/playfab-docs/api-references/events/player-device-info.md index ef5fc87b0..509c7ddb3 100644 --- a/playfab-docs/api-references/events/player-device-info.md +++ b/playfab-docs/api-references/events/player-device-info.md @@ -23,18 +23,4 @@ This event is triggered once after the player logs in based on the settings for ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-display-name-filtered.md b/playfab-docs/api-references/events/player-display-name-filtered.md index d31e81661..f8227fdaf 100644 --- a/playfab-docs/api-references/events/player-display-name-filtered.md +++ b/playfab-docs/api-references/events/player-display-name-filtered.md @@ -23,18 +23,4 @@ This event is triggered when a display name is filtered by community sift only i ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-displayname-changed.md b/playfab-docs/api-references/events/player-displayname-changed.md index 17bdbd85c..3074abf6f 100644 --- a/playfab-docs/api-references/events/player-displayname-changed.md +++ b/playfab-docs/api-references/events/player-displayname-changed.md @@ -24,18 +24,4 @@ This event is triggered when a player's display name is changed. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-executed-cloudscript.md b/playfab-docs/api-references/events/player-executed-cloudscript.md index 71e1778ce..61018b58b 100644 --- a/playfab-docs/api-references/events/player-executed-cloudscript.md +++ b/playfab-docs/api-references/events/player-executed-cloudscript.md @@ -24,18 +24,4 @@ This event is optionally triggered when a CloudScript function is executed, eith ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-inventory-item-added.md b/playfab-docs/api-references/events/player-inventory-item-added.md index c719d6049..d0a5e094a 100644 --- a/playfab-docs/api-references/events/player-inventory-item-added.md +++ b/playfab-docs/api-references/events/player-inventory-item-added.md @@ -32,18 +32,4 @@ This event is triggered when an item is granted to a player. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-linked-account.md b/playfab-docs/api-references/events/player-linked-account.md index 75147cb6b..1e0070203 100644 --- a/playfab-docs/api-references/events/player-linked-account.md +++ b/playfab-docs/api-references/events/player-linked-account.md @@ -26,18 +26,4 @@ This event is triggered when a new authentication method is linked to a player's ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-logged-in.md b/playfab-docs/api-references/events/player-logged-in.md index fa2b19cf9..96776ea58 100644 --- a/playfab-docs/api-references/events/player-logged-in.md +++ b/playfab-docs/api-references/events/player-logged-in.md @@ -26,18 +26,4 @@ This event is triggered when a player logs in. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-paid-for-purchase.md b/playfab-docs/api-references/events/player-paid-for-purchase.md index b6fd32bd3..d61370899 100644 --- a/playfab-docs/api-references/events/player-paid-for-purchase.md +++ b/playfab-docs/api-references/events/player-paid-for-purchase.md @@ -32,18 +32,4 @@ This event is triggered when the second step of the payment process completes, p ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-password-reset-link-sent.md b/playfab-docs/api-references/events/player-password-reset-link-sent.md index 162a629f8..4b5c9907a 100644 --- a/playfab-docs/api-references/events/player-password-reset-link-sent.md +++ b/playfab-docs/api-references/events/player-password-reset-link-sent.md @@ -27,18 +27,4 @@ This event is triggered when a player is sent a link to reset their password. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-photon-session-authenticated.md b/playfab-docs/api-references/events/player-photon-session-authenticated.md index 214ae0e69..874d5c28a 100644 --- a/playfab-docs/api-references/events/player-photon-session-authenticated.md +++ b/playfab-docs/api-references/events/player-photon-session-authenticated.md @@ -24,18 +24,4 @@ Properties ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ranked-on-leaderboard-version.md b/playfab-docs/api-references/events/player-ranked-on-leaderboard-version.md index 879e3be6c..2b3cbfbac 100644 --- a/playfab-docs/api-references/events/player-ranked-on-leaderboard-version.md +++ b/playfab-docs/api-references/events/player-ranked-on-leaderboard-version.md @@ -27,18 +27,4 @@ This event is triggered for the top-ranked players on a leaderboard when the lea ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-realmoney-purchase.md b/playfab-docs/api-references/events/player-realmoney-purchase.md index b244930f6..bcd43b8ff 100644 --- a/playfab-docs/api-references/events/player-realmoney-purchase.md +++ b/playfab-docs/api-references/events/player-realmoney-purchase.md @@ -30,18 +30,4 @@ This event is triggered when a player makes a real money purchase, and generates ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-receipt-validation.md b/playfab-docs/api-references/events/player-receipt-validation.md index d7dfcab6f..e6863fcd3 100644 --- a/playfab-docs/api-references/events/player-receipt-validation.md +++ b/playfab-docs/api-references/events/player-receipt-validation.md @@ -27,18 +27,4 @@ This event is triggered when a player attempts to make a real money purchase and ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-redeemed-coupon.md b/playfab-docs/api-references/events/player-redeemed-coupon.md index 1dccbeb9c..bbd75a90c 100644 --- a/playfab-docs/api-references/events/player-redeemed-coupon.md +++ b/playfab-docs/api-references/events/player-redeemed-coupon.md @@ -24,18 +24,4 @@ This event is triggered when a player redeems a coupon. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-registered-push-notifications.md b/playfab-docs/api-references/events/player-registered-push-notifications.md index fc91dfa49..d59348226 100644 --- a/playfab-docs/api-references/events/player-registered-push-notifications.md +++ b/playfab-docs/api-references/events/player-registered-push-notifications.md @@ -24,18 +24,4 @@ This event is triggered when a player registers for push notifications. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-removed-title.md b/playfab-docs/api-references/events/player-removed-title.md index 9f9880c55..4624f3fbb 100644 --- a/playfab-docs/api-references/events/player-removed-title.md +++ b/playfab-docs/api-references/events/player-removed-title.md @@ -22,18 +22,4 @@ This event is triggered when a player account for a title is removed. Note: this ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-reported-as-abusive.md b/playfab-docs/api-references/events/player-reported-as-abusive.md index 27ccae2fc..6adc548a6 100644 --- a/playfab-docs/api-references/events/player-reported-as-abusive.md +++ b/playfab-docs/api-references/events/player-reported-as-abusive.md @@ -24,18 +24,4 @@ This event is triggered when a player is reported by another player as abusive. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-set-profile-property.md b/playfab-docs/api-references/events/player-set-profile-property.md index c3af40086..6654394ec 100644 --- a/playfab-docs/api-references/events/player-set-profile-property.md +++ b/playfab-docs/api-references/events/player-set-profile-property.md @@ -24,18 +24,4 @@ This event is triggered when PlayFab makes an internal adjustment to a player pr ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-started-purchase.md b/playfab-docs/api-references/events/player-started-purchase.md index 5a724bc8e..2f34a3ef9 100644 --- a/playfab-docs/api-references/events/player-started-purchase.md +++ b/playfab-docs/api-references/events/player-started-purchase.md @@ -26,18 +26,4 @@ This event is triggered when a player starts a purchase. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-statistic-changed.md b/playfab-docs/api-references/events/player-statistic-changed.md index befbfdc9f..55a3c7c37 100644 --- a/playfab-docs/api-references/events/player-statistic-changed.md +++ b/playfab-docs/api-references/events/player-statistic-changed.md @@ -28,18 +28,4 @@ This event is triggered when a player statistic is changed. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-statistic-deleted.md b/playfab-docs/api-references/events/player-statistic-deleted.md index dae5187aa..b3ef4ce1d 100644 --- a/playfab-docs/api-references/events/player-statistic-deleted.md +++ b/playfab-docs/api-references/events/player-statistic-deleted.md @@ -26,18 +26,4 @@ This event is triggered when a player statistic is deleted. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-tag-added.md b/playfab-docs/api-references/events/player-tag-added.md index eb7d9f58f..353a81dbc 100644 --- a/playfab-docs/api-references/events/player-tag-added.md +++ b/playfab-docs/api-references/events/player-tag-added.md @@ -24,18 +24,4 @@ This event is triggered when a tag is added to a player profile. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-tag-removed.md b/playfab-docs/api-references/events/player-tag-removed.md index 377e3886a..fadc9c1ff 100644 --- a/playfab-docs/api-references/events/player-tag-removed.md +++ b/playfab-docs/api-references/events/player-tag-removed.md @@ -24,18 +24,4 @@ This event is triggered when a tag is removed from a player profile. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-triggered-action-executed-cloudscript.md b/playfab-docs/api-references/events/player-triggered-action-executed-cloudscript.md index a72dbe173..84329c0f4 100644 --- a/playfab-docs/api-references/events/player-triggered-action-executed-cloudscript.md +++ b/playfab-docs/api-references/events/player-triggered-action-executed-cloudscript.md @@ -27,18 +27,4 @@ This event is triggered when a CloudScript function is run as the result of a Pl ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-unlinked-account.md b/playfab-docs/api-references/events/player-unlinked-account.md index 2341570f7..5bcb86db8 100644 --- a/playfab-docs/api-references/events/player-unlinked-account.md +++ b/playfab-docs/api-references/events/player-unlinked-account.md @@ -24,18 +24,4 @@ This event is triggered when an authentication method is unlinked from a player' ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-updated-contact-email.md b/playfab-docs/api-references/events/player-updated-contact-email.md index 9e0a48510..fdfa83a46 100644 --- a/playfab-docs/api-references/events/player-updated-contact-email.md +++ b/playfab-docs/api-references/events/player-updated-contact-email.md @@ -25,18 +25,4 @@ This event is triggered when a player updates a contact email on their profile. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-vc-item-purchased.md b/playfab-docs/api-references/events/player-vc-item-purchased.md index 0d6c0ad25..a6633a480 100644 --- a/playfab-docs/api-references/events/player-vc-item-purchased.md +++ b/playfab-docs/api-references/events/player-vc-item-purchased.md @@ -29,18 +29,4 @@ This event is triggered when the player makes a purchase using virtual currency. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-verified-contact-email.md b/playfab-docs/api-references/events/player-verified-contact-email.md index 6dc84d36f..14489ac0e 100644 --- a/playfab-docs/api-references/events/player-verified-contact-email.md +++ b/playfab-docs/api-references/events/player-verified-contact-email.md @@ -24,18 +24,4 @@ This event is triggered when a contact email is verified for a player. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-virtual-currency-balance-changed.md b/playfab-docs/api-references/events/player-virtual-currency-balance-changed.md index 040e347e0..98f0fc5b8 100644 --- a/playfab-docs/api-references/events/player-virtual-currency-balance-changed.md +++ b/playfab-docs/api-references/events/player-virtual-currency-balance-changed.md @@ -26,18 +26,4 @@ This event is triggered when a player's virtual currency balance changes. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/review-reported.md b/playfab-docs/api-references/events/review-reported.md index f381e5a28..40fd565dd 100644 --- a/playfab-docs/api-references/events/review-reported.md +++ b/playfab-docs/api-references/events/review-reported.md @@ -24,21 +24,6 @@ This event is triggered when a review is reported. |Reason|String|The string reason for this report.| |CreatorEntityKey|[EntityKey](data-types/entitykey.md)|The EntityKey of the creator of the review that was reported.| - ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"review_reported"| -|EventNamespace|String|"playfab.catalog"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/reviews-takedown-requested.md b/playfab-docs/api-references/events/reviews-takedown-requested.md index 62966a3a3..bf59b245f 100644 --- a/playfab-docs/api-references/events/reviews-takedown-requested.md +++ b/playfab-docs/api-references/events/reviews-takedown-requested.md @@ -22,18 +22,4 @@ Event trigged when a takedown of reviews is requested. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|"reviews_takedown_requested"| -|EventNamespace|String|"playfab.catalog"| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/secret-added.md b/playfab-docs/api-references/events/secret-added.md index 5d583087f..f8d08f1ff 100644 --- a/playfab-docs/api-references/events/secret-added.md +++ b/playfab-docs/api-references/events/secret-added.md @@ -19,26 +19,9 @@ This event is triggered when a multiplayer server secret is added. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[SecretAddedEventPayload](data-types/secretaddedeventpayload.md)|The multiplayer server secret added event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/secret-deleted.md b/playfab-docs/api-references/events/secret-deleted.md index f50df6f67..a32aee78f 100644 --- a/playfab-docs/api-references/events/secret-deleted.md +++ b/playfab-docs/api-references/events/secret-deleted.md @@ -19,26 +19,9 @@ This event is triggered when a multiplayer server secret is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[SecretDeletedEventPayload](data-types/secretdeletedeventpayload.md)|The multiplayer server secret deleted event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/sent-email.md b/playfab-docs/api-references/events/sent-email.md index ce0008772..eb32b0daf 100644 --- a/playfab-docs/api-references/events/sent-email.md +++ b/playfab-docs/api-references/events/sent-email.md @@ -33,18 +33,4 @@ This event is triggered when an email is sent or fails to send to a player. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/sent-push-notification.md b/playfab-docs/api-references/events/sent-push-notification.md index a990fbd6f..dddd28587 100644 --- a/playfab-docs/api-references/events/sent-push-notification.md +++ b/playfab-docs/api-references/events/sent-push-notification.md @@ -30,18 +30,4 @@ This event is triggered when a push notification is sent or fails to be sent to ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/server-requested.md b/playfab-docs/api-references/events/server-requested.md index 47fd0cae3..08f9b556a 100644 --- a/playfab-docs/api-references/events/server-requested.md +++ b/playfab-docs/api-references/events/server-requested.md @@ -19,27 +19,12 @@ This event is triggered when a multiplayer server is requested. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| + |Payload|[ServerRequestedEventPayload](data-types/serverrequestedeventpayload.md)|The multiplayer server requested event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| -## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: +## Common Properties -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/server-state-changed.md b/playfab-docs/api-references/events/server-state-changed.md index 4386c2bae..a07a1b372 100644 --- a/playfab-docs/api-references/events/server-state-changed.md +++ b/playfab-docs/api-references/events/server-state-changed.md @@ -19,25 +19,10 @@ This event is triggered when a multiplayer server's state is changed. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| + |Payload|[ServerStateChangedEventPayload](data-types/serverstatechangedeventpayload.md)|The multiplayer server state changed event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| -## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: +## Common Properties -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/statistic-updated.md b/playfab-docs/api-references/events/statistic-updated.md index c9b35dff4..c97dd19e0 100644 --- a/playfab-docs/api-references/events/statistic-updated.md +++ b/playfab-docs/api-references/events/statistic-updated.md @@ -28,18 +28,4 @@ This event is triggered when a statistic is updated for a given entity. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/studio-created.md b/playfab-docs/api-references/events/studio-created.md index 72a361834..23121f972 100644 --- a/playfab-docs/api-references/events/studio-created.md +++ b/playfab-docs/api-references/events/studio-created.md @@ -24,18 +24,4 @@ This event is triggered when a studio is created. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/studio-tier-updated.md b/playfab-docs/api-references/events/studio-tier-updated.md index 10cede10d..5de1d38f9 100644 --- a/playfab-docs/api-references/events/studio-tier-updated.md +++ b/playfab-docs/api-references/events/studio-tier-updated.md @@ -34,18 +34,4 @@ This event is triggered when a studio tier is updated. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/studio-user-added.md b/playfab-docs/api-references/events/studio-user-added.md index 5c58581a6..a8847b0fa 100644 --- a/playfab-docs/api-references/events/studio-user-added.md +++ b/playfab-docs/api-references/events/studio-user-added.md @@ -27,18 +27,4 @@ ms.localizationpriority: medium ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/studio-user-invited.md b/playfab-docs/api-references/events/studio-user-invited.md index 0133dc54a..f6052de64 100644 --- a/playfab-docs/api-references/events/studio-user-invited.md +++ b/playfab-docs/api-references/events/studio-user-invited.md @@ -30,18 +30,4 @@ This event is triggererd when a user is invited to a studio. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/studio-user-removed.md b/playfab-docs/api-references/events/studio-user-removed.md index 9bc47c94c..fa0853d5c 100644 --- a/playfab-docs/api-references/events/studio-user-removed.md +++ b/playfab-docs/api-references/events/studio-user-removed.md @@ -28,18 +28,4 @@ This event is triggered when a user is removed from a studio. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/tenancy-connector-onboard.md b/playfab-docs/api-references/events/tenancy-connector-onboard.md index eb347e6b4..4eb3a8897 100644 --- a/playfab-docs/api-references/events/tenancy-connector-onboard.md +++ b/playfab-docs/api-references/events/tenancy-connector-onboard.md @@ -23,18 +23,4 @@ This event is triggered when a tenancy connector is onboarded. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-aborted-task.md b/playfab-docs/api-references/events/title-aborted-task.md index 199247ca3..3028d3c2d 100644 --- a/playfab-docs/api-references/events/title-aborted-task.md +++ b/playfab-docs/api-references/events/title-aborted-task.md @@ -24,18 +24,4 @@ This event is triggered when a task instance is aborted. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-added-cloudscript.md b/playfab-docs/api-references/events/title-added-cloudscript.md index ae46e7de5..97c9c07f9 100644 --- a/playfab-docs/api-references/events/title-added-cloudscript.md +++ b/playfab-docs/api-references/events/title-added-cloudscript.md @@ -27,18 +27,4 @@ This event is triggered when new CloudScript is uploaded to PlayFab. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-api-settings-changed.md b/playfab-docs/api-references/events/title-api-settings-changed.md index d833ef143..8c7339fd1 100644 --- a/playfab-docs/api-references/events/title-api-settings-changed.md +++ b/playfab-docs/api-references/events/title-api-settings-changed.md @@ -25,18 +25,4 @@ This event is triggered when an API Features setting is changed for the title. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-catalog-updated.md b/playfab-docs/api-references/events/title-catalog-updated.md index 391eeb1ae..f6104f133 100644 --- a/playfab-docs/api-references/events/title-catalog-updated.md +++ b/playfab-docs/api-references/events/title-catalog-updated.md @@ -25,18 +25,4 @@ This event is triggered when a catalog is changed. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-client-rate-limited-alert.md b/playfab-docs/api-references/events/title-client-rate-limited-alert.md index ac556030a..7ce5e82b7 100644 --- a/playfab-docs/api-references/events/title-client-rate-limited-alert.md +++ b/playfab-docs/api-references/events/title-client-rate-limited-alert.md @@ -27,18 +27,4 @@ This event is triggered when a single IP address generates too many API calls to ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-completed-task.md b/playfab-docs/api-references/events/title-completed-task.md index 02b774b92..bb56acf98 100644 --- a/playfab-docs/api-references/events/title-completed-task.md +++ b/playfab-docs/api-references/events/title-completed-task.md @@ -27,18 +27,4 @@ This event is triggered when a scheduled task has completed ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-created-task.md b/playfab-docs/api-references/events/title-created-task.md index c322a4363..40414e40f 100644 --- a/playfab-docs/api-references/events/title-created-task.md +++ b/playfab-docs/api-references/events/title-created-task.md @@ -23,18 +23,4 @@ This event is triggered when a task is created. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-deleted-master-player.md b/playfab-docs/api-references/events/title-deleted-master-player.md index 8ea9bfcc1..10e686b6a 100644 --- a/playfab-docs/api-references/events/title-deleted-master-player.md +++ b/playfab-docs/api-references/events/title-deleted-master-player.md @@ -24,18 +24,4 @@ This event is triggered when a GDPR delete is finished. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-deleted-task.md b/playfab-docs/api-references/events/title-deleted-task.md index f35609a0c..b78f70b6b 100644 --- a/playfab-docs/api-references/events/title-deleted-task.md +++ b/playfab-docs/api-references/events/title-deleted-task.md @@ -25,18 +25,4 @@ This event is triggered when a task is deleted. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-deleted.md b/playfab-docs/api-references/events/title-deleted.md index 7dae3e639..39d5aba34 100644 --- a/playfab-docs/api-references/events/title-deleted.md +++ b/playfab-docs/api-references/events/title-deleted.md @@ -16,18 +16,4 @@ This event is triggered when a game title is deleted. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-exceeded-limit.md b/playfab-docs/api-references/events/title-exceeded-limit.md index e202620ef..c8163f111 100644 --- a/playfab-docs/api-references/events/title-exceeded-limit.md +++ b/playfab-docs/api-references/events/title-exceeded-limit.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # title_exceeded_limit -This event is triggererd when a title exceeds a service limit and receives an error. +This event is triggered when a title exceeds a service limit and receives an error. ## Properties @@ -27,18 +27,4 @@ This event is triggererd when a title exceeds a service limit and receives an er ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-high-error-rate-alert.md b/playfab-docs/api-references/events/title-high-error-rate-alert.md index 39e6c7cd5..258a46e21 100644 --- a/playfab-docs/api-references/events/title-high-error-rate-alert.md +++ b/playfab-docs/api-references/events/title-high-error-rate-alert.md @@ -27,18 +27,4 @@ This event is triggered when a game title experiences a high rate of errors. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-initiated-player-password-reset.md b/playfab-docs/api-references/events/title-initiated-player-password-reset.md index b350fff6b..40bf72bd1 100644 --- a/playfab-docs/api-references/events/title-initiated-player-password-reset.md +++ b/playfab-docs/api-references/events/title-initiated-player-password-reset.md @@ -26,18 +26,4 @@ This event is triggered when a title initiates the account recovery process for ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-limit-changed.md b/playfab-docs/api-references/events/title-limit-changed.md index aa58ef5bf..0ff09a6df 100644 --- a/playfab-docs/api-references/events/title-limit-changed.md +++ b/playfab-docs/api-references/events/title-limit-changed.md @@ -29,18 +29,4 @@ This event is triggered when a title changes a service limit. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-news-updated.md b/playfab-docs/api-references/events/title-news-updated.md index e8a4d7c0d..71882bc84 100644 --- a/playfab-docs/api-references/events/title-news-updated.md +++ b/playfab-docs/api-references/events/title-news-updated.md @@ -25,18 +25,4 @@ This event is triggered when a title news is created or updated. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-permission-policy-changed.md b/playfab-docs/api-references/events/title-permission-policy-changed.md index 0e0addc01..2b72afa18 100644 --- a/playfab-docs/api-references/events/title-permission-policy-changed.md +++ b/playfab-docs/api-references/events/title-permission-policy-changed.md @@ -25,18 +25,4 @@ This event is triggered when an update occurs to a a title's permission policies ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-profile-view-constraints-changed.md b/playfab-docs/api-references/events/title-profile-view-constraints-changed.md index e8ddc6ba7..f3dff05ec 100644 --- a/playfab-docs/api-references/events/title-profile-view-constraints-changed.md +++ b/playfab-docs/api-references/events/title-profile-view-constraints-changed.md @@ -26,18 +26,4 @@ This event is triggered when a profile view constraint is changed for the title. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-published-cloudscript.md b/playfab-docs/api-references/events/title-published-cloudscript.md index 8cd6c515f..fa69a854b 100644 --- a/playfab-docs/api-references/events/title-published-cloudscript.md +++ b/playfab-docs/api-references/events/title-published-cloudscript.md @@ -24,18 +24,4 @@ An inactive revision of CloudScript has been made into the active 'live' version ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-queue-config-updated.md b/playfab-docs/api-references/events/title-queue-config-updated.md index 3f2e8a888..6a9394c68 100644 --- a/playfab-docs/api-references/events/title-queue-config-updated.md +++ b/playfab-docs/api-references/events/title-queue-config-updated.md @@ -25,18 +25,4 @@ This event is triggered when a queue config is changed. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/title-requested-limit-change.md b/playfab-docs/api-references/events/title-requested-limit-change.md index 0f35391fd..c4b52b7fd 100644 --- a/playfab-docs/api-references/events/title-requested-limit-change.md +++ b/playfab-docs/api-references/events/title-requested-limit-change.md @@ -33,18 +33,4 @@ This event is triggered when a title requests a service limit change. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-saved-survey.md b/playfab-docs/api-references/events/title-saved-survey.md index f5aae4c76..0291fac07 100644 --- a/playfab-docs/api-references/events/title-saved-survey.md +++ b/playfab-docs/api-references/events/title-saved-survey.md @@ -27,18 +27,4 @@ This event is triggered when a game's survey is saved. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-scheduled-cloudscript-executed.md b/playfab-docs/api-references/events/title-scheduled-cloudscript-executed.md index 58dd5bc5f..21afe10bc 100644 --- a/playfab-docs/api-references/events/title-scheduled-cloudscript-executed.md +++ b/playfab-docs/api-references/events/title-scheduled-cloudscript-executed.md @@ -24,18 +24,4 @@ This event is triggered when a CloudScript function is run by a scheduled task. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-secret-key-changed.md b/playfab-docs/api-references/events/title-secret-key-changed.md index c7c9d7831..77e5001ad 100644 --- a/playfab-docs/api-references/events/title-secret-key-changed.md +++ b/playfab-docs/api-references/events/title-secret-key-changed.md @@ -28,18 +28,4 @@ This event is triggered when a title adds or updates a Secret Key ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-started-task.md b/playfab-docs/api-references/events/title-started-task.md index 16f5a3bf5..f01f3ec40 100644 --- a/playfab-docs/api-references/events/title-started-task.md +++ b/playfab-docs/api-references/events/title-started-task.md @@ -28,18 +28,4 @@ This event is triggered when a task is scheduled to run. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-statistic-version-changed.md b/playfab-docs/api-references/events/title-statistic-version-changed.md index 8f0706151..370825e4f 100644 --- a/playfab-docs/api-references/events/title-statistic-version-changed.md +++ b/playfab-docs/api-references/events/title-statistic-version-changed.md @@ -25,18 +25,4 @@ This event is triggered when the version of a statistic changes, causing its lea ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-store-updated.md b/playfab-docs/api-references/events/title-store-updated.md index d872b8d6b..1a5261799 100644 --- a/playfab-docs/api-references/events/title-store-updated.md +++ b/playfab-docs/api-references/events/title-store-updated.md @@ -26,18 +26,4 @@ This event is triggered when a store is changed. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-updated-task.md b/playfab-docs/api-references/events/title-updated-task.md index 39a2b55a2..b533193d5 100644 --- a/playfab-docs/api-references/events/title-updated-task.md +++ b/playfab-docs/api-references/events/title-updated-task.md @@ -25,18 +25,4 @@ This event is triggered when a task is updated. ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/vm-assigned.md b/playfab-docs/api-references/events/vm-assigned.md index 5a3ceedc1..050f9d82b 100644 --- a/playfab-docs/api-references/events/vm-assigned.md +++ b/playfab-docs/api-references/events/vm-assigned.md @@ -19,25 +19,8 @@ This event is triggered when a virtual machine is assigned to a multiplayer serv |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[VmAssignedEventPayload](data-types/vmassignedeventpayload.md)|The multiplayer server virtual machine assigned event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-game-certificates-deployed.md b/playfab-docs/api-references/events/vm-game-certificates-deployed.md index 03f799863..d5c8f4206 100644 --- a/playfab-docs/api-references/events/vm-game-certificates-deployed.md +++ b/playfab-docs/api-references/events/vm-game-certificates-deployed.md @@ -19,26 +19,8 @@ This event is triggered when game certificates are deployed in a game virtual ma |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[VmGameCertificatesDeployedEventPayload](data-types/vmgamecertificatesdeployedeventpayload.md)|The multiplayer server vm game certificates deployed event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| - +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/vm-remote-user-created.md b/playfab-docs/api-references/events/vm-remote-user-created.md index 640701d81..c2a19609a 100644 --- a/playfab-docs/api-references/events/vm-remote-user-created.md +++ b/playfab-docs/api-references/events/vm-remote-user-created.md @@ -19,25 +19,8 @@ This event is triggered when a multiplayer server virtual machine remote user is |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[VmRemoteUserCreatedEventPayload](data-types/vmremoteusercreatedeventpayload.md)|The multiplayer server virtual machine remote user created event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-remote-user-deleted.md b/playfab-docs/api-references/events/vm-remote-user-deleted.md index 97076ab22..d3fb0b72c 100644 --- a/playfab-docs/api-references/events/vm-remote-user-deleted.md +++ b/playfab-docs/api-references/events/vm-remote-user-deleted.md @@ -19,25 +19,8 @@ This event is triggered when a multiplayer server virtual machine remote user is |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[VmRemoteUserDeletedEventPayload](data-types/vmremoteuserdeletedeventpayload.md)|The multiplayer server virtual machine remote user deleted event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-state-change.md b/playfab-docs/api-references/events/vm-state-change.md index 049d00a4d..f26bd9350 100644 --- a/playfab-docs/api-references/events/vm-state-change.md +++ b/playfab-docs/api-references/events/vm-state-change.md @@ -19,26 +19,9 @@ This event is triggered when a multiplayer virtual machine's state is changed. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[VmStateChangeEventPayload](data-types/vmstatechangeeventpayload.md)|The multiplayer server vm state change event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-unassignment-started.md b/playfab-docs/api-references/events/vm-unassignment-started.md index c51cb5bcf..17ef1a416 100644 --- a/playfab-docs/api-references/events/vm-unassignment-started.md +++ b/playfab-docs/api-references/events/vm-unassignment-started.md @@ -18,25 +18,8 @@ This event is triggered when a virtual machine is unassigned from a multiplayer |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[VmUnassignmentStartedEventPayload](data-types/vmunassignmentstartedeventpayload.md)|The multiplayer server virtual machine unassignment started event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-unhealthy.md b/playfab-docs/api-references/events/vm-unhealthy.md index b1b601daa..c72655d16 100644 --- a/playfab-docs/api-references/events/vm-unhealthy.md +++ b/playfab-docs/api-references/events/vm-unhealthy.md @@ -18,25 +18,8 @@ This event is triggered when a virtual machine is found to be unhealthy. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| -|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| |Payload|[VmUnhealthyEventPayload](data-types/vmunhealthyeventpayload.md)|The multiplayer server virtual machine unhealthy event payload.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -All PlayStream events are formatted as JSON objects and share the following common properties: - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| -|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| -|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| -|EventId|String|PlayFab-assigned unique identifier for this event.| -|EventName|String|The name of this event.| -|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| -|History|[PlayStreamEventHistory](data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| -|Reserved|object|Reserved exclusively for PlayFab internal use.| -|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| -|SourceType|[SourceType](data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| -|Timestamp|DateTime|The time (in UTC) associated with this event.| +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/includes/_common-properties-eventsv1.md b/playfab-docs/includes/_common-properties-eventsv1.md new file mode 100644 index 000000000..8b89af9c4 --- /dev/null +++ b/playfab-docs/includes/_common-properties-eventsv1.md @@ -0,0 +1,12 @@ +All V1 PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](../api-references/events/data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| \ No newline at end of file diff --git a/playfab-docs/includes/_common-properties-eventsv2.md b/playfab-docs/includes/_common-properties-eventsv2.md new file mode 100644 index 000000000..572862134 --- /dev/null +++ b/playfab-docs/includes/_common-properties-eventsv2.md @@ -0,0 +1,12 @@ +All V2 PlayStream events are formatted as JSON objects and most share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|SchemaVersion|String|PlayStream event format version, following a semantic versioning scheme.| +|FullName|[Object](../api-references/events/data-types/fullnameobject.md)|Combination of the event name and event namespace to fully specify the event type.| +|Id|String|PlayFab-assigned unique identifier for this event.| +|Timestamp|DateTime|The time (in UTC) associated with this event.| +|Entity|[Object](../api-references/events/data-types/entityobject.md)|Details about the entity to which this event applies including Entity Id and Entity type.| +|Originator|[Object](../api-references/events/data-types/originatorobject.md)|Object describing the source and source type that initiated this event.| +|PayloadContentType|String|Specifies the content of the event payload. Default is "JSON".| +|Origin Info|Object|Optional field containing info about events originating outside of PlayFab.| \ No newline at end of file diff --git a/playfab-docs/sdks/toc.yml b/playfab-docs/sdks/toc.yml index 5d6c16d7a..60e41850c 100644 --- a/playfab-docs/sdks/toc.yml +++ b/playfab-docs/sdks/toc.yml @@ -144,7 +144,7 @@ items: - name: Overview href: ../multiplayer/servers/server-sdks.md - name: Unreal Server SDK - href: ../multiplayer/servers/server-sdks/toc.yml + href: ../multiplayer/servers/server-sdks/unreal-gsdk/toc.yml - name: Tools and utilities href: tools/index.yml items: From 1598d1d20b03f62048dfb6b88389e259905750ee Mon Sep 17 00:00:00 2001 From: Aleksandra Zakrzewska <47401245+alzakrze@users.noreply.github.com> Date: Thu, 22 Jan 2026 13:20:16 -0800 Subject: [PATCH 20/76] Add game save telemetry/playstream event documentation (#2780) --- .../events/data-types/gamesaveconflict.md | 20 +++++++++++ .../events/gamesave-version-finalized.md | 34 +++++++++++++++++++ .../gamesave-version-marked-known-good.md | 26 ++++++++++++++ playfab-docs/api-references/events/index.md | 8 +++++ 4 files changed, 88 insertions(+) create mode 100644 playfab-docs/api-references/events/data-types/gamesaveconflict.md create mode 100644 playfab-docs/api-references/events/gamesave-version-finalized.md create mode 100644 playfab-docs/api-references/events/gamesave-version-marked-known-good.md diff --git a/playfab-docs/api-references/events/data-types/gamesaveconflict.md b/playfab-docs/api-references/events/data-types/gamesaveconflict.md new file mode 100644 index 000000000..3ad1941e1 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/gamesaveconflict.md @@ -0,0 +1,20 @@ +--- +title: GameSaveConflict +author: alzakrze +description: GameSaveConflict data type. +ms.author: alzakrze +ms.date: 01/22/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events, gamesave +ms.localizationpriority: medium +--- + +# GameSaveConflict + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ConflictingVersion|Int64|The ID of the version that was in conflict with this version. That version should be assumed to have the opposite IsWinner value.| +|IsWinner|Boolean|Whether this version is the winner of the conflict resolution process.| diff --git a/playfab-docs/api-references/events/gamesave-version-finalized.md b/playfab-docs/api-references/events/gamesave-version-finalized.md new file mode 100644 index 000000000..ef5e2e217 --- /dev/null +++ b/playfab-docs/api-references/events/gamesave-version-finalized.md @@ -0,0 +1,34 @@ +--- +title: gamesave_version_finalized +author: alzakrze +description: gamesave_version_finalized event. +ms.author: alzakrze +ms.date: 01/22/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events, gamesave +ms.localizationpriority: medium +--- + +# gamesave_version_finalized + +This event is triggered when a game save version is finalized with all the files fully uploaded. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Version|Int64|The version of the game save that was finalized.| +|PlayerIdentityProvider|String|The login identity provider used by the player uploading the game save.| +|DeviceType|String|The type of device used for this game save version.| +|FinalizedAt|DateTime|The time at which the game save version was finalized.| +|NewFileCount|Int32|The number of new files that were added to the game save store for this version.| +|NewFilesSizeBytes|Int64|The size in bytes of the new files that were added to the game save store for this version.| +|TotalFileCount|Int32|The total number of files that were included in the finalized game save version.| +|TotalSizeBytes|Int64|The total size in bytes of the finalized game save version, including all files.| +|IsGeneratedByRollback|Boolean|Whether the version was generated and finalized by a rollback operation.| +|Conflict|[GameSaveConflict](data-types/gamesaveconflict.md)|Data about any conflict that occurred during the finalization of the game save version. This will usually be null if the version was not finalized during a conflict resolution operation.| + +## Common Properties + +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/gamesave-version-marked-known-good.md b/playfab-docs/api-references/events/gamesave-version-marked-known-good.md new file mode 100644 index 000000000..f55a07650 --- /dev/null +++ b/playfab-docs/api-references/events/gamesave-version-marked-known-good.md @@ -0,0 +1,26 @@ +--- +title: gamesave_version_marked_known_good +author: alzakrze +description: gamesave_version_marked_known_good event. +ms.author: alzakrze +ms.date: 01/22/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events, gamesave +ms.localizationpriority: medium +--- + +# gamesave_version_marked_known_good + +This event is triggered when a game save version is marked as known good. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|MarkedAt|DateTime|The time at which the game save version was marked as known good.| +|Version|Int64|The version of the game save that was marked as known good.| + +## Common Properties + +[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 4b6c1d4d7..dcad1ba89 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -248,6 +248,14 @@ Each event type has a set of properties that are included as part of event's dat - [items_updated](items-updated.md) Event raised when items have been updated in an inventory. +## GameSave + +- [gamesave_version_finalized](gamesave-version-finalized.md) + This event is triggered when a game save version is finalized with all the files fully uploaded. + +- [gamesave_version_marked_known_good](gamesave-version-marked-known-good.md) + This event is triggered when a game save version is marked as known good. + ## Partner - [display_name_filtered](display-name-filtered.md) From 6b17e51a16c18164ed30d912752131904b7f7d43 Mon Sep 17 00:00:00 2001 From: Scott Munro Date: Mon, 26 Jan 2026 14:41:32 -0800 Subject: [PATCH 21/76] PFMultiplayer: Refresh errors doc page + include pubsub errors (#2781) * update public pfmultiplayer errors * fix date --- .../pfmultiplayererrors.md | 243 +++++++++++------- 1 file changed, 147 insertions(+), 96 deletions(-) diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayererrors.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayererrors.md index 88accee13..1e2a7982e 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayererrors.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayererrors.md @@ -1,11 +1,11 @@ --- author: ScottMunroMS title: "PlayFab Multiplayer C++ SDK Error Codes" -description: "Error codes used by the PlayFab Multiplayer, Lobby and Matchmaking APIs" +description: "Error codes used by the PlayFab Multiplayer, Lobby, and Matchmaking APIs" ms.author: scmunro ms.topic: reference ms.service: azure-playfab -ms.date: 08/19/2022 +ms.date: 01/23/2026 --- # PlayFab Multiplayer C++ SDK Error Codes @@ -15,110 +15,161 @@ The following error codes are used by the PlayFab Multiplayer, Lobby and Matchma For additional guidance on handling these errors, check out [Handling Lobby and Matchmaking C++ SDK errors](../lobby-and-matchmaking-client-sdk-errors.md) ### Multiplayer + | Hex | Dec | Description | | ------ | ------ | ------ | -| 0x89236400 | -1994169344 | The PlayFabMultiplayer library must be initialized. | -| 0x89236401 | -1994169343 | Only one PlayFabMultiplayer instance can exist at a time. | -| 0x89236402 | -1994169342 | No PlayFab entity token was associated with the provided entity key. Use PFMultiplayerSetEntityToken to associate a PlayFab entity token with a PlayFab entity key before passing that entity key to the API. | -| 0x89236403 | -1994169341 | The provided multiplayer thread ID is invalid/unknown. | -| 0x89236404 | -1994169340 | The provided PlayFab entity key is malformed or otherwise invalid. | -| 0x89236405 | -1994169339 | The Microsoft Game Core XNetworking feature is unavailable | -| 0x89236406 | -1994169338 | The PlayFab Multiplayer library couldn't be initialized because the Game Core Network stack wasn't initialized. Use the Microsoft Game Core XNetworkingGetConnectivityHint API to determine when the network stack is initialized. | -| 0x89236408 | -1994169336 | The operation was canceled due to the title suspending. | -| 0x89236409 | -1994169335 | The PlayFab service returned an unexpected error with a 4XX status code. | -| 0x8923640A | -1994169334 | The PlayFab service returned an unexpected error with a 5XX status code. | -| 0x8923640B | -1994169333 | The Entity ID is invalid. | -| 0x8923640C | -1994169332 | The Entity Type is invalid or unsupported. | -| 0x8923640D | -1994169331 | A request rate limit was exceeded. The request wasn't automatically retried again because retries are disabled or the retry-after period was too long. | +| 0x89236400 | -1994169344 | The PlayFabMultiplayer library must be initialized. | +| 0x89236401 | -1994169343 | Only one PlayFabMultiplayer instance can exist at a time. | +| 0x89236402 | -1994169342 | No PlayFab entity token was associated with the provided entity key. Use PFMultiplayerSetEntityToken to associate a PlayFab entity token with a PlayFab entity key before passing that entity key to the API. | +| 0x89236403 | -1994169341 | The provided multiplayer thread ID is invalid/unknown. | +| 0x89236404 | -1994169340 | The provided PlayFab entity key is malformed or otherwise invalid. | +| 0x89236405 | -1994169339 | The Microsoft Game Core XNetworking feature is unavailable. | +| 0x89236406 | -1994169338 | The PlayFab Multiplayer library couldn't be initialized because the Game Core Network stack wasn't initialized. Use the Microsoft Game Core XNetworkingGetConnectivityHint API to determine when the network stack is initialized. | +| 0x89236408 | -1994169336 | The operation was canceled due to the title suspending. | +| 0x89236409 | -1994169335 | The PlayFab service returned an unexpected error with a 4XX status code. | +| 0x8923640A | -1994169334 | The PlayFab service returned an unexpected error with a 5XX status code. | +| 0x8923640B | -1994169333 | The Entity ID is invalid. | +| 0x8923640C | -1994169332 | The Entity Type is invalid or unsupported. | +| 0x8923640D | -1994169331 | A request rate limit was exceeded. The request wasn't automatically retried again because retries are disabled or the retry-after period was too long. | ### Lobby + | Hex | Dec | Description | | ------ | ------ | ------ | -| 0x89236200 | -1994169856 | Can't create local user; local user limit reached. | -| 0x89236202 | -1994169854 | A user with the provided entity ID already exists. | -| 0x89236203 | -1994169853 | Requested, provided, or configured Lobby owner migration policy is invalid. | -| 0x89236204 | -1994169852 | Requested, provided, or configured Lobby access policy is invalid. | -| 0x89236205 | -1994169851 | Requested object is still pending asynchronous creation. | -| 0x89236206 | -1994169850 | The provided max member count value is outside of the allowed range of values. | -| 0x89236207 | -1994169849 | Provided lobby property count exceeds maximum allowed. | -| 0x89236208 | -1994169848 | Encountered an unexpected error. | -| 0x89236209 | -1994169847 | Failed to parse json data. | -| 0x8923620B | -1994169845 | A parameter or value provided to the PlayFab service was invalid. | -| 0x8923620C | -1994169844 | An unexpected error code was returned by the PlayFab service. | -| 0x8923620D | -1994169843 | The provided entity token has expired. | -| 0x8923620E | -1994169842 | The user isn't authorized to execute the operation. | -| 0x89236212 | -1994169838 | An unknown error code was returned by the PlayFab service. | -| 0x89236213 | -1994169837 | The PlayFab entity token is malformed or otherwise invalid. | -| 0x89236214 | -1994169836 | The specified Lobby entity ID is invalid. | -| 0x89236215 | -1994169835 | The provided property bag contains duplicate property keys. | -| 0x89236216 | -1994169834 | A Lobby request rate limit was exceeded. The request wasn't automatically retried again because retries are disabled or the retry-after period was too long. | -| 0x89236217 | -1994169833 | The owner of the lobby isn't a member of the lobby. | -| 0x8923621A | -1994169830 | The operation couldn't be completed because the entity provided wasn't locally authenticated. Log in the entity first and provide the library a token using SetEntityToken. | -| 0x8923621B | -1994169829 | The provided Lobby state change type is invalid/unknown. | -| 0x8923621C | -1994169828 | The provided Lobby state change result is invalid/unknown. | -| 0x8923621D | -1994169827 | The provided Lobby disconnect reason is invalid/unknown. | -| 0x8923621E | -1994169826 | The PlayFab service returned unexpected 'bad request' error. | -| 0x8923621F | -1994169825 | The provided Lobby thread ID is invalid/unknown. | -| 0x89236220 | -1994169824 | The operation couldn't be completed because the entity provided wasn't a member of the lobby. | -| 0x89236221 | -1994169823 | The PlayFab service returned an invalid/malformed response. | -| 0x89236222 | -1994169822 | Either a lobby update or a member update must be provided. | -| 0x89236223 | -1994169821 | Updates can't be queued after disconnecting from the lobby. | -| 0x89236224 | -1994169820 | The provided lobby join request contained an invalid property deletion. | -| 0x89236225 | -1994169819 | The requested user was already a member of the lobby. | -| 0x89236226 | -1994169818 | The requested lobby doesn't exist. | -| 0x89236227 | -1994169817 | The requested lobby wasn't in a joinable state. | -| 0x89236228 | -1994169816 | The provided Lobby member removed reason is invalid/unknown. | -| 0x89236229 | -1994169815 | The operation couldn't be completed because the acting member wasn't the owner. | -| 0x8923622A | -1994169814 | Lobby member can't self-promote to owner while owner is still connected using current owner migration policy. | -| 0x8923622B | -1994169813 | The arrangement string version isn't supported. | -| 0x8923622C | -1994169812 | An arrangement string for the specified entity key wasn't found in the packed arrangement string. | -| 0x8923622D | -1994169811 | The arrangement string is an invalid format and couldn't be parsed. | -| 0x8923622E | -1994169810 | Requested, provided, or configured Lobby invite listener status is invalid. | -| 0x8923622F | -1994169809 | The invite listener is already set and must be stopped before resetting. | -| 0x89236230 | -1994169808 | The invite listener isn't set and so can't be stopped. | -| 0x89236231 | -1994169807 | Requested, provided, or configured Lobby membership lock is invalid. | -| 0x89236232 | -1994169806 | The member can't rejoin the lobby because they have been banned. | -| 0x89236233 | -1994169805 | The member can't join the lobby because they are already concurrently a member of the maximum number of allowed lobbies. | -| 0x89236234 | -1994169804 | The owner can't promote disconnected member to owner if owner migration policy is Automatic. | -| 0x89236235 | -1994169803 | The connection status is invalid. | +| 0x89236200 | -1994169856 | Can't create local user; local user limit reached. | +| 0x89236202 | -1994169854 | A user with the provided entity ID already exists. | +| 0x89236203 | -1994169853 | Requested, provided, or configured Lobby owner migration policy is invalid. | +| 0x89236204 | -1994169852 | Requested, provided, or configured Lobby access policy is invalid. | +| 0x89236205 | -1994169851 | Requested object is still pending asynchronous creation. | +| 0x89236206 | -1994169850 | The provided max member count value is outside of the allowed range of values. | +| 0x89236207 | -1994169849 | Provided lobby property count exceeds maximum allowed. | +| 0x89236208 | -1994169848 | Encountered an unexpected error. | +| 0x89236209 | -1994169847 | Failed to parse json data. | +| 0x8923620B | -1994169845 | A parameter or value provided to the PlayFab service was invalid. | +| 0x8923620C | -1994169844 | The PlayFab service returned an unexpected error. | +| 0x8923620D | -1994169843 | The provided entity token has expired. | +| 0x8923620E | -1994169842 | The user isn't authorized to execute the operation. | +| 0x89236212 | -1994169838 | The PlayFab Service returned an unknown error. | +| 0x89236213 | -1994169837 | The PlayFab entity token is malformed or otherwise invalid. | +| 0x89236214 | -1994169836 | The specified Lobby entity ID is invalid. | +| 0x89236215 | -1994169835 | The provided property bag contains duplicate property keys. | +| 0x89236216 | -1994169834 | A Lobby request rate limit was exceeded. The request wasn't automatically retried again because retries are disabled or the retry-after period was too long. | +| 0x89236217 | -1994169833 | The owner of the lobby isn't a member of the lobby. | +| 0x8923621A | -1994169830 | The operation couldn't be completed because the entity provided wasn't locally authenticated. Log in the entity first, and provide the library a token using SetEntityToken. | +| 0x8923621B | -1994169829 | The provided Lobby state change type is invalid/unknown. | +| 0x8923621C | -1994169828 | The provided Lobby state change result is invalid/unknown. | +| 0x8923621D | -1994169827 | The provided Lobby disconnect reason is invalid/unknown. | +| 0x8923621E | -1994169826 | The PlayFab service returned unexpected 'bad request' error. | +| 0x8923621F | -1994169825 | The provided Lobby thread ID is invalid/unknown. | +| 0x89236220 | -1994169824 | The operation couldn't be completed because the entity provided wasn't a member of the lobby. | +| 0x89236221 | -1994169823 | The PlayFab service returned an invalid/malformed response. | +| 0x89236222 | -1994169822 | Either a lobby update or a member update must be provided. | +| 0x89236223 | -1994169821 | Updates can't be queued after disconnecting from the lobby. | +| 0x89236224 | -1994169820 | The provided lobby join request contained an invalid property deletion. | +| 0x89236225 | -1994169819 | The requested user was already a member of the lobby. | +| 0x89236226 | -1994169818 | The requested lobby doesn't exist. | +| 0x89236227 | -1994169817 | The requested lobby wasn't in a joinable state. | +| 0x89236228 | -1994169816 | The provided Lobby member removed reason is invalid/unknown. | +| 0x89236229 | -1994169815 | The operation couldn't be completed because the acting member wasn't the owner. | +| 0x8923622A | -1994169814 | Lobby member can't self-promote to owner while owner is still connected using current owner migration policy. | +| 0x8923622B | -1994169813 | The arrangement string version isn't supported. | +| 0x8923622C | -1994169812 | An arrangement string for the specified entity key wasn't found in the packed arrangement string. | +| 0x8923622D | -1994169811 | The arrangement string is an invalid format and couldn't be parsed. | +| 0x8923622E | -1994169810 | Requested, provided, or configured Lobby invite listener status is invalid. | +| 0x8923622F | -1994169809 | The invite listener is already set and must be stopped before resetting. | +| 0x89236230 | -1994169808 | The invite listener isn't set and so can't be stopped. | +| 0x89236231 | -1994169807 | Requested, provided, or configured Lobby membership lock is invalid. | +| 0x89236232 | -1994169806 | The member can't rejoin the lobby because they have been banned. | +| 0x89236233 | -1994169805 | The member can't join the lobby because they are already concurrently a member of the maximum number of allowed lobbies. | +| 0x89236234 | -1994169804 | The owner can't promote disconnected member to owner if owner migration policy is Automatic. | +| 0x89236235 | -1994169803 | The connection status is invalid. | +| 0x89236236 | -1994169802 | Operation can only be performed by the lobby's server-owner. | +| 0x89236237 | -1994169801 | The specified calling server hasn't joined the lobby. The lobby has a different server joined. | +| 0x89236238 | -1994169800 | The lobby doesn't have a joined server. | +| 0x89236239 | -1994169799 | The lobby already has a joined server. | +| 0x8923623A | -1994169798 | The server has already joined the lobby. | +| 0x8923623B | -1994169797 | The server can't join a lobby which isn't client-owned. | +| 0x8923623C | -1994169796 | The server can't join a lobby which doesn't use connections. | +| 0x8923623D | -1994169795 | Operation can only be performed by the non-owning server associated with the lobby. | +| 0x8923623E | -1994169794 | The connection status is invalid. | ### Matchmaking + +| Hex | Dec | Description | +| ------ | ------ | ------ | +| 0x89236300 | -1994169600 | The provided matchmaking ticket status is invalid/unknown. | +| 0x89236301 | -1994169599 | The provided matchmaking ticket result is invalid/unknown. | +| 0x89236302 | -1994169598 | The provided matchmaking ticket cancel reason is invalid/unknown. | +| 0x89236303 | -1994169597 | The provided matchmaking state change type is invalid/unknown. | +| 0x89236304 | -1994169596 | The ticket was canceled due to a cancelation request. | +| 0x89236305 | -1994169595 | The ticket was canceled due to a service error. | +| 0x89236306 | -1994169594 | The ticket was canceled because the timeout elapsed before a match could be found. | +| 0x89236307 | -1994169593 | The ticket was canceled for an unknown reason. | +| 0x89236308 | -1994169592 | Duplicate users aren't allowed in the ticket parameters. | +| 0x89236309 | -1994169591 | At least one local user must be specified in the ticket parameters. | +| 0x8923630A | -1994169590 | There were too many users in the ticket for the queue. | +| 0x8923630B | -1994169589 | The ticket is already completed. | +| 0x8923630C | -1994169588 | Encountered an unrecoverable failure when attempting to cancel the ticket. | +| 0x8923630D | -1994169587 | One of the users is a member of too many tickets. | +| 0x8923630F | -1994169585 | A matchmaking request rate limit was exceeded. The request wasn't automatically retried again because retries are disabled or the retry-after period was too long. | +| 0x89236310 | -1994169584 | The timeout elapsed without the service completing the ticket. | +| 0x89236311 | -1994169583 | The calling entity is invalid. | +| 0x89236312 | -1994169582 | One of the users in the ticket has invalid attributes. | +| 0x89236313 | -1994169581 | The queue wasn't found. | +| 0x89236314 | -1994169580 | The match wasn't found. | +| 0x89236315 | -1994169579 | The ticket wasn't found. | +| 0x89236316 | -1994169578 | The user already joined the ticket. | +| 0x89236317 | -1994169577 | The queue config is invalid. | +| 0x89236318 | -1994169576 | One of the users in the ticket has an invalid entity profile. | +| 0x89236319 | -1994169575 | Matchmaking isn't enabled for this title. | +| 0x8923631A | -1994169574 | One of the users in the ticket has attributes that are too large. | +| 0x8923631B | -1994169573 | One of the ticket attributes is invalid. | +| 0x8923631C | -1994169572 | The user hasn't joined the ticket. | +| 0x8923631D | -1994169571 | The number of queues has exceeded the limit for this title. | +| 0x8923631E | -1994169570 | The API called doesn't match the type of ticket requested. | +| 0x8923631F | -1994169569 | The request was malformed. | +| 0x89236320 | -1994169568 | Match details can only be provided when the ticket is in the matched state. | +| 0x89236321 | -1994169567 | The provided multiplayer protocol type is invalid. | +| 0x89236322 | -1994169566 | The ticket was canceled by the service. | + +### PubSub + | Hex | Dec | Description | | ------ | ------ | ------ | -| 0x89236300 | -1994169600 | The provided matchmaking ticket status is invalid/unknown. | -| 0x89236301 | -1994169599 | The provided matchmaking ticket result is invalid/unknown. | -| 0x89236302 | -1994169598 | The provided matchmaking ticket cancel reason is invalid/unknown. | -| 0x89236303 | -1994169597 | The provided matchmaking state change type is invalid/unknown. | -| 0x89236304 | -1994169596 | The ticket was canceled due to a cancelation request. | -| 0x89236305 | -1994169595 | The ticket was canceled due to a service error. | -| 0x89236306 | -1994169594 | The ticket was canceled because the timeout elapsed before a match could be found. | -| 0x89236307 | -1994169593 | The ticket was canceled for an unknown reason. | -| 0x89236308 | -1994169592 | Duplicate users aren't allowed in the ticket parameters. | -| 0x89236309 | -1994169591 | At least one local user must be specified in the ticket parameters. | -| 0x8923630A | -1994169590 | There were too many users in the ticket for the queue. | -| 0x8923630B | -1994169589 | The ticket is already completed. | -| 0x8923630C | -1994169588 | Encountered an unrecoverable failure when attempting to cancel the ticket. | -| 0x8923630D | -1994169587 | One of the users is a member of too many tickets. | -| 0x8923630F | -1994169585 | A matchmaking request rate limit was exceeded. The request wasn't automatically retried again because retries are disabled or the retry-after period was too long. | -| 0x89236310 | -1994169584 | The timeout elapsed without the service completing the ticket. | -| 0x89236311 | -1994169583 | The calling entity is invalid. | -| 0x89236312 | -1994169582 | One of the users in the ticket has invalid attributes. | -| 0x89236313 | -1994169581 | The queue wasn't found. | -| 0x89236314 | -1994169580 | The match wasn't found. | -| 0x89236315 | -1994169579 | The ticket wasn't found. | -| 0x89236316 | -1994169578 | The user already joined the ticket. | -| 0x89236317 | -1994169577 | The queue config is invalid. | -| 0x89236318 | -1994169576 | One of the users in the ticket has an invalid entity profile. | -| 0x89236319 | -1994169575 | Matchmaking isn't enabled for this title. | -| 0x8923631A | -1994169574 | One of the users in the ticket has attributes that are too large. | -| 0x8923631B | -1994169573 | One of the ticket attributes is invalid. | -| 0x8923631C | -1994169572 | The user hasn't joined the ticket. | -| 0x8923631D | -1994169571 | The number of queues has exceeded the limit for this title. | -| 0x8923631E | -1994169570 | The API called doesn't match the type of ticket requested. | -| 0x8923631F | -1994169569 | The request was malformed. | -| 0x89236320 | -1994169568 | Match details can only be provided when the ticket is in the matched state. | -| 0x89236321 | -1994169567 | The provided multiplayer protocol type is invalid. | -| 0x89236322 | -1994169566 | The ticket was canceled by the service. | +| 0x89236600 | -1994168832 | The PubSub library must be initialized. | +| 0x89236601 | -1994168831 | Only one PubSubManager instance can exist at a time. | +| 0x09236602 | 153314818 | The requested operation failed because the PubSub API is still in use. | +| 0x89236603 | -1994168829 | The specified PubSub entity ID is invalid. | +| 0x89236604 | -1994168828 | The requested operation failed because the PubSub entity is still in use. | +| 0x89236605 | -1994168827 | Encountered an exception while parsing and adding the PubSub connection ID to a PlayFab message body. | +| 0x89236606 | -1994168826 | Failed to parse json data. | +| 0x89236607 | -1994168825 | The PubSub library is already unsubscribed from the provided PubSub subscription. | +| 0x89236608 | -1994168824 | Failed to create a PubSub connection string. | +| 0x89236609 | -1994168823 | The PubSub service encountered an error while creating or maintaining the connection. | +| 0x8923660A | -1994168822 | Encountered an exception while parsing connection identifier. | +| 0x8923660B | -1994168821 | The requested entity wasn't found. | +| 0x8923660C | -1994168820 | The provided connection exists but is in an invalid/unknown state. | +| 0x8923660D | -1994168819 | Encountered an unexpected exception when attempting to establish PubSub connection. | +| 0x8923660E | -1994168818 | Encountered an unexpected exception when parsing a subscription event. | +| 0x8923660F | -1994168817 | Encountered an unexpected exception when parsing a subscription notification payload. | +| 0x89236610 | -1994168816 | Attempted to establish a PubSub subscription without any available PubSub connections. | +| 0x89236611 | -1994168815 | The PubSub service declined the attempt to subscribe to the specified resource. | +| 0x89236612 | -1994168814 | Failed to end the PubSub session while attempting to disconnect. | +| 0x89236613 | -1994168813 | The Microsoft Game Core XNetworking feature is unavailable. | +| 0x89236614 | -1994168812 | The PubSub library couldn't be initialized because the Game Core Network stack wasn't initialized. Use the Microsoft Game Core XNetworkingGetConnectivityHint API to determine when the network stack is initialized. | +| 0x89236616 | -1994168810 | Unable to set up signalr websocket connection. | +| 0x89236617 | -1994168809 | The PubSub library has hit its max websocket connections limit. | +| 0x89236618 | -1994168808 | The PubSub connection has hit its max entity limit. | +| 0x89236619 | -1994168807 | The PubSub service doesn't recognize the entity type. | +| 0x8923661A | -1994168806 | The PubSub service doesn't recognize the request type. | +| 0x8923661B | -1994168805 | The PubSub service was unavailable via SignalR. | +| 0x8923661C | -1994168804 | The PubSub service returned an unexpected response. | +| 0x8923661D | -1994168803 | The PubSub service is throttling the client over signalr due to exceeding the rate limit. | +| 0x8923661E | -1994168802 | The PlayFab service returned an unexpected error with a 4XX status code. | +| 0x8923661F | -1994168801 | The PlayFab service returned an unexpected error with a 5XX status code. | +| 0x89236620 | -1994168800 | The PubSub service failed to deliver a subscription confirmation within a reasonable timeout. | +| 0x89236621 | -1994168799 | The PubSub service failed due to lack of authentication credentials to a specific resource. | +| 0x89236622 | -1994168798 | Failed to access PubSub services; check credentials. | ## Global HRESULT error codes From bff531eb39f740d870f88f107ebc3aac685142dd Mon Sep 17 00:00:00 2001 From: Scott Munro Date: Mon, 26 Jan 2026 14:52:10 -0800 Subject: [PATCH 22/76] PlayFabParty: Refresh errors doc page from auto-generated source (#2782) The core intent of this PR is to update the Party error doc reference pages to be exactly what is generated by our internal reference doc generator scripts (rather than something hand crafted) doing so has also opportunistically cleaned up some stale/deprecated errors. --- .../multiplayer/networking/reference/partyerrors.md | 6 ++---- .../multiplayer/networking/xblreference/partyxblerrors.md | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/playfab-docs/multiplayer/networking/reference/partyerrors.md b/playfab-docs/multiplayer/networking/reference/partyerrors.md index 55351e44a..400a2a3cd 100644 --- a/playfab-docs/multiplayer/networking/reference/partyerrors.md +++ b/playfab-docs/multiplayer/networking/reference/partyerrors.md @@ -5,7 +5,7 @@ description: Error codes used by PlayFab Party APIs ms.author: scmunro ms.topic: reference ms.service: azure-playfab -ms.date: 08/11/2022 +ms.date: 01/25/2026 --- # PlayFab Party Error Codes @@ -153,8 +153,6 @@ The following error codes are used by the PlayFab Party APIs: | 0x1058 | 4184 | The provided target chat control list contained at least one duplicate chat control. | | 0x1059 | 4185 | The provided target endpoint list contained at least one duplicate endpoint. | | 0x105A | 4186 | A platform error resulted in failure to determine the preferred UI language. | -| 0x105B | 4187 | XAudio 2.7 debug version not installed on system (install the DirectX SDK Developer Runtime). | -| 0x105C | 4188 | XAudio 2.7 not installed on system (install the DirectX End-user Runtimes (June 2010)). | | 0x105E | 4190 | Authentication was attempted for a user that is already authenticated. | | 0x1062 | 4194 | The text-to-speech synthesis request was rejected by the service for being too large. | | 0x1063 | 4195 | The text-to-speech synthesis request was throttled. | @@ -264,6 +262,7 @@ The following error codes are used by the PlayFab Party APIs: | 0x112C | 4396 | The region quality measurement minimum required successful responses value is invalid. | | 0x112D | 4397 | The region quality measurement ideal number of successful responses value is invalid. | | 0x1136 | 4406 | The network is being destroyed because it is idle. | +| 0x113C | 4412 | The user default platform audio device monitor is uninitialized; it may have failed or be unsupported on this platform. | ## Platform-specific errors | Hex | Dec | Description | @@ -293,7 +292,6 @@ The following error codes are used by the PlayFab Party APIs: | 0x301C | 12316 | A user matching the ID wasn't found in the Microsoft gaming runtime. | | 0x301D | 12317 | There isn't a default user for the Microsoft gaming runtime. | | 0x301E | 12318 | The Microsoft gaming runtime failed to resolve a required user privilege. | -| 0x301F | 12319 | The Microsoft gaming XNetworking feature is unavailable. | | 0x3020 | 12320 | The network stack must be initialized before calling PartyManager::Initialize(); use the Microsoft Game Core XNetworkingGetConnectivityHint API to determine when the network stack is initialized. | | 0x3021 | 12321 | Callers must pass a port value of 0 when the PartyLocalUdpSocketBindAddressOptions::ExcludeGameCorePreferredUdpMultiplayerPort option is set. | | 0x3022 | 12322 | It's invalid to pass PartyLocalUdpSocketBindAddressOptions::ExcludeGameCorePreferredUdpMultiplayerPort in all versions of PlayFab Party except for the Microsoft Game Core version. | diff --git a/playfab-docs/multiplayer/networking/xblreference/partyxblerrors.md b/playfab-docs/multiplayer/networking/xblreference/partyxblerrors.md index 02212f651..958f9c251 100644 --- a/playfab-docs/multiplayer/networking/xblreference/partyxblerrors.md +++ b/playfab-docs/multiplayer/networking/xblreference/partyxblerrors.md @@ -5,13 +5,13 @@ description: List of error codes used by the PlayFab Party's Xbox Live Helper Li ms.author: scmunro ms.topic: reference ms.service: azure-playfab -ms.date: 08/11/2022 +ms.date: 01/25/2026 --- # PlayFab Party Xbox Live Helper Library Error Codes The following error codes are used by the PlayFab Party Xbox Live Helper Library: -## Xbox Live Helper Library Errors +## Xbox Live Helper Library errors | Hex | Dec | Description | | --- | --- | ----------- | | 0x5000 | 20480 | Only one instance of PartyXblManager can exist at a time. | @@ -30,4 +30,4 @@ The following error codes are used by the PlayFab Party Xbox Live Helper Library | 0x500F | 20495 | The specified correlation ID didn't match any outstanding requests. | | 0x5014 | 20500 | Setting profiling callbacks after PartyXblManager initialization is forbidden. | | 0x5015 | 20501 | The request failed because the Xbox Live token was invalid. | -| 0x5016 | 20502 | The request failed because the Xbox Live token was expired. | \ No newline at end of file +| 0x5016 | 20502 | The request failed because the Xbox Live token was expired. | From c85b06df859b97991e40c14c03a5194ee7d25488 Mon Sep 17 00:00:00 2001 From: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Date: Tue, 27 Jan 2026 07:38:33 -0800 Subject: [PATCH 23/76] Sony trademark edits 60869667 (#2783) Edited Sony trademark symbols in two files . --- playfab-docs/sdks/c/index.md | 4 ++-- playfab-docs/sdks/platforms/playstation.md | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/playfab-docs/sdks/c/index.md b/playfab-docs/sdks/c/index.md index 15c3395cb..7611116bb 100644 --- a/playfab-docs/sdks/c/index.md +++ b/playfab-docs/sdks/c/index.md @@ -30,7 +30,7 @@ Before you can access the PlayFab Services SDK for Nintendo Switch, you need to Once you've been granted access to the Switch SDK, you can download it from the git repo here: [PlayFabCSdk.Switch](https://dev.azure.com/PlayFabPrivate/Switch/_git/PlayFabCSdk.Switch). -## PlayStation® +## PlayStation 5 / PlayStation 4 Confirm your developer status on the PlayFab page in the middleware directory of the developer portal before accessing the PlayFab Services SDK for PlayStation. For more information, see [Request access](../request-access-for-sdks-samples.md). @@ -78,7 +78,7 @@ There are scenarios where this SDK isn't appropriate: - Linux - The Linux version of this SDK is available via GitHub. Follow the instructions here to start making basic calls to PlayFab: [Quickstart for Linux](./quickstart-linux.md). - Playstation - - See [Playstation](#playstation) + - See [PlayStation 5 / PlayStation 4](#playstation-5--playstation-4) - Nintendo Switch - See [Nintendo Switch](#nintendo-switch) diff --git a/playfab-docs/sdks/platforms/playstation.md b/playfab-docs/sdks/platforms/playstation.md index 6f3b1da5c..769a8fa3a 100644 --- a/playfab-docs/sdks/platforms/playstation.md +++ b/playfab-docs/sdks/platforms/playstation.md @@ -27,8 +27,4 @@ Our PlayFab Services SDKs for Unreal and Unity are platform-agnostic. As such, t To utilize our C/C++ or Legacy C++ SDKs on PS4 and PS5, you must confirm your developer status via DevNet. Once you have approval, we can grant access to the SDK. Learn more about this process here: [Request Access](../request-access-for-sdks-samples.md). -"PlayStation" is a registered trademark or trademark of Sony Interactive Entertainment Inc. - -"PS4" is a registered trademark or trademark of Sony Interactive Entertainment Inc. - -"PS5" is a registered trademark or trademark of Sony Interactive Entertainment Inc. +"PlayStation", "PS5", and "PS4" are registered trademarks or trademarks of Sony Interactive Entertainment Inc. From 8bfc72c9c85c58b14a8b3acf521080d4eee13d4f Mon Sep 17 00:00:00 2001 From: Keith Kline <43284035+keithrkline@users.noreply.github.com> Date: Wed, 28 Jan 2026 13:32:17 -0800 Subject: [PATCH 24/76] Kkline lobby (#2786) * Revise lobby invites documentation Updated note format and clarified invite restrictions. * Add RestrictInvitesToLobbyOwner property description New property added * Improve note formatting in join-lobbies.md Updated the note format for clarity and consistency. * Document client-owned lobby access from server Added information about client-owned lobby access from a server and related APIs. * Fix API link for JoinLobbyAsServer Updated link for JoinLobbyAsServer API to point to the correct documentation. * Clarify client owned lobby access for game servers Updated the section on client owned lobby access to clarify the role of 'game_server' entities and added a table summarizing relevant APIs. * Update REST API table for game server interactions Added the SDK C++ APIs * Fix typo in owner requirements and privileges documentation Corrected a typo in the documentation regarding the APIs for client-owned lobbies. * Update Player Entity attribute source warning Clarified the use of Player Entity as an attribute source by adding a warning against using it with external entity types. --- playfab-docs/multiplayer/lobby/join-lobbies.md | 3 ++- playfab-docs/multiplayer/lobby/lobby-invites.md | 4 +++- playfab-docs/multiplayer/lobby/lobby-properties.md | 1 + .../lobby/owner-requirements-and-privileges.md | 13 +++++++++++++ .../multiplayer/matchmaking/config-queues.md | 2 +- 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/playfab-docs/multiplayer/lobby/join-lobbies.md b/playfab-docs/multiplayer/lobby/join-lobbies.md index 9f5aba747..fdb06af0c 100644 --- a/playfab-docs/multiplayer/lobby/join-lobbies.md +++ b/playfab-docs/multiplayer/lobby/join-lobbies.md @@ -22,7 +22,8 @@ Players can discover connection strings and join lobbies in the following ways. 1. By searching for available lobbies with [FindLobbies](find-lobbies.md) and joining an available lobby 1. By sharing the lobby's connection string via any out-of-band, custom discovery mechanism -> NOTE: Only players (i.e. title_player_account PlayFab entities) can join lobbies as members. Game servers (i.e. game_server PlayFab entities) cannot join lobbies as members. For more information on the how game servers interact with lobbies, see [Game Servers and Lobbies](lobby-server-overview.md). +> [!NOTE] +> Only players (i.e. title_player_account PlayFab entities) can join lobbies as members. Game servers (i.e. game_server PlayFab entities) cannot join lobbies as members. For more information on the how game servers interact with lobbies, see [Game Servers and Lobbies](lobby-server-overview.md). ## Connection strings and Lobby IDs diff --git a/playfab-docs/multiplayer/lobby/lobby-invites.md b/playfab-docs/multiplayer/lobby/lobby-invites.md index 80fa45b20..b98f90312 100644 --- a/playfab-docs/multiplayer/lobby/lobby-invites.md +++ b/playfab-docs/multiplayer/lobby/lobby-invites.md @@ -15,7 +15,8 @@ ms.localizationpriority: medium This article provides an overview of Lobby invites and how to use them in the Lobby and Matchmaking SDK. -> NOTE: Only players (i.e. title_player_account PlayFab entities) can send or receive invites. Game servers (i.e. game_server PlayFab entities) cannot. For more information on the how game servers interact with lobbies, see [Game Servers and Lobbies](lobby-server-overview.md). +> [!NOTE] +> Only players (i.e. title_player_account PlayFab entities) can send or receive invites. Game servers (i.e. game_server PlayFab entities) cannot. For more information on the how game servers interact with lobbies, see [Game Servers and Lobbies](lobby-server-overview.md). ## Invite types @@ -27,6 +28,7 @@ There are two types of invites your game is likely to make use of. ### Joining a lobby by in-game invites * A member of a lobby may invite another player to that lobby directly via the lobby service. +* The lobby owner can choose to restrict sending invites to only the owner via the lobby property __RestrictInvitesToLobbyOwner__ * This invite shares the lobby's connection string with the invited player. * The invited player receives the invitation via __PFLobbyInviteReceivedStateChange__ and can use the attached connection string to join the lobby. * These invites work cross-platform but only work in-game. diff --git a/playfab-docs/multiplayer/lobby/lobby-properties.md b/playfab-docs/multiplayer/lobby/lobby-properties.md index a95c413a5..5fd575953 100644 --- a/playfab-docs/multiplayer/lobby/lobby-properties.md +++ b/playfab-docs/multiplayer/lobby/lobby-properties.md @@ -28,6 +28,7 @@ Each lobby has a set of pre-defined properties commonly needed for most game sce | ownerMigrationPolicy | Policy determines how a new owner will be chosen. To learn more, see [Ownership changes](ownership-changes.md). | | accessPolicy | Policy indicates who can discover the lobby's connection string. This property can only be changed by the owner. | | membershipLock | This value indicates whether new members may join the lobby or not. When __Locked__, new members may not join. When __Unlocked__ new members may join. This property can only be changed by the owner. | +| RestrictInvitesToLobbyOwner | A setting that controls whether only the lobby owner can send invites to join the lobby. When true, only the lobby owner can send invites. When false or not specified, any member can send invites. Defaults to false if not specified. Restricted to client owned lobbies.| ## Custom Properties diff --git a/playfab-docs/multiplayer/lobby/owner-requirements-and-privileges.md b/playfab-docs/multiplayer/lobby/owner-requirements-and-privileges.md index 301e80a53..751d8bfd5 100644 --- a/playfab-docs/multiplayer/lobby/owner-requirements-and-privileges.md +++ b/playfab-docs/multiplayer/lobby/owner-requirements-and-privileges.md @@ -44,6 +44,19 @@ The owner of a lobby has privileges that non-owning members of the lobby don't h * In server-owned lobbies, the owner can only assign another server as the new owner. * In client-owned lobbies, the owner can only assign another member as the new owner. +## Client-owned lobby access from a game_server + +When using a client-owned lobby, you might have the need to securely put data into the lobby from a server. APIs have been added or modified to allow this scenario, so that you can use a 'game_server' entity to join and update the lobby for this purpose. 'ServerData' is similar to 'LobbyData' but it can only be added by a 'game_server' entity. This allows you store important information for other clients to read, such as server connection data, where you can trust the source of the data and even the client lobby owner can't modify it. + +| REST API | C++ SDK | Description | +|-----------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|-------------------------------------| +| [JoinLobbyAsServer](../../../../rest/api/playfab/multiplayer/lobby/join-lobby-as-server) | [PFMultiplayerJoinLobbyAsServer](playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerjoinlobbyasserver) | Join a client-owned lobby from a 'game_server'. A lobby owner cannot remove a connected 'game_server', and only one 'game_server' can be joined at a time | +| [UpdateLobbyAsServer](../../../../rest/api/playfab/multiplayer/lobby/update-lobby-as-server) | [PFLobbyServerPostUpdateAsServer](playfabmultiplayerreference-cpp/pflobby/functions/pflobbyserverpostupdateasserver) | Update a lobby's ServerData object from a connected 'game_server' | +| [LeaveLobbyAsServer](../../../../rest/api/playfab/multiplayer/lobby/leave-lobby-as-server) | [PFLobbyServerLeaveServer](playfabmultiplayerreference-cpp/pflobby/functions/pflobbyserverleaveasserver) | Leave a client owned lobby from a 'game_server' gracefully, ServerData contents remain | +| [GetLobby](../../../../rest/api/playfab/multiplayer/lobby/get-lobby) | Not necessary, happens on Join | Get a lobby when a 'game_server' is joined to it | +| [FindLobbies](../../../../rest/api/playfab/multiplayer/lobby/find-lobbies) | [PFMultiplayerFindLobbies](playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies) | Find lobbies that the 'game_server' is associated with | + + ## See also * [Lobby properties](lobby-properties.md) diff --git a/playfab-docs/multiplayer/matchmaking/config-queues.md b/playfab-docs/multiplayer/matchmaking/config-queues.md index 3dc88c658..1d71c9192 100644 --- a/playfab-docs/multiplayer/matchmaking/config-queues.md +++ b/playfab-docs/multiplayer/matchmaking/config-queues.md @@ -65,7 +65,7 @@ The elements below are often used by all rules. + **Attribute Source** - Rules often act upon information that is provided to them. This field describes two options for the source of this information: 1. **User** - Attributes are submitted alongside players in the create or join ticket request. - 2. **Player Entity** - Attributes are retrieved from the player's associated Player Entity. These can be set via the [SetObjects API](xref:titleid.playfabapi.com.data.object.setobjects) + 2. **Player Entity** - Attributes are retrieved from the player's associated Player Entity. These can be set via the [SetObjects API](xref:titleid.playfabapi.com.data.object.setobjects). DO NOT use this source when using external entity types. + **Attribute Path** - The path to reach the attribute. When using a User Attribute Source, it is simply the name of the attribute. When using a Player Entity Attribute Source, it is a [JSONPath](https://github.com/json-path/JsonPath) that retrieves a particular item from the entity, such as `$.playerSkill.Mean`. + **Behavior when attribute is not specified** - If a rule requires an attribute, but none is specified, the rule may be configured with one of two behaviors: From 7b2ef7c2990c2114bd667d02efb12b6fa895ba5f Mon Sep 17 00:00:00 2001 From: foxvalo <218149361+foxvalo@users.noreply.github.com> Date: Thu, 29 Jan 2026 09:37:07 -0800 Subject: [PATCH 25/76] ADO 59008382: Clarify Azure Blob SAS permissions (#2785) Co-authored-by: v-foxval@microsoft.com --- .../export-data/data-connection-azure-blob.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md b/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md index 6e2945b81..74233d2cf 100644 --- a/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md +++ b/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md @@ -11,7 +11,7 @@ ms.localizationpriority: medium --- # Configuring your Azure Storage Data Connection -First, you need an Azure subscription and a storage account. +First, you need an Azure subscription and a storage account. For existing PlayFab and Azure customers, you can create a storage container on the [Azure portal](https://ms.portal.azure.com/#allservices) and get started with Data Connections on [Azure PlayFab](https://developer.playfab.com/en-US/sign-up). @@ -36,13 +36,13 @@ For PlayFab to ingest data in your storage account, container details along with - Go to the right of the main window and select the three ellipses associated with your chosen container. - Select **Generate SAS** from the dropdown menu to open the **Generate SAS** window. -![Screenshot of SAS token on the container level - Option 1](media/SAS-token-on-the-container-level-1.png "SAS token on the container level - Option 1") +![Screenshot of SAS token on the container level - Option 1](media/SAS-token-on-the-container-level-1.png "SAS token on the container level - Option 1") - Define **Permissions** by selecting or clearing the appropriate checkbox. Make sure the **Create** and **Write** permissions are selected. -![Screenshot of Generate SAS token - Option 1](media/Generate-SAS-token-level.png "Generate SAS token - Option 1") +![Screenshot of Generate SAS token - Option 1](media/Generate-SAS-token-level.png "Generate SAS token - Option 1") -- Specify the signed key **Start** and **Expiry** times. +- Specify the signed key **Start** and **Expiry** times. - Select **Generate SAS token and URL**. - The **Blob SAS token** query string appears in the lower area of the window. - Copy and paste the **Blob SAS token** values into a **secure location for use in the Azure PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. @@ -51,23 +51,23 @@ For PlayFab to ingest data in your storage account, container details along with > [!Important] > Generate and retrieve the shared access signature for your storage account itself. -- In the [Azure portal](https://ms.portal.azure.com/#allservices), select **Your storage account** +- In the [Azure portal](https://ms.portal.azure.com/#allservices), select **Your storage account** - Select a **Shared access signature** from the list under **Security + Networking**. -- Define **Services** by selecting **blob** and clearing other checkboxes. -- Define **Resource Type** by selecting **Object** and clearing other checkboxes. -- Make sure the **Create** and **Write** permissions are selected. -- Specify the signed key **Start** and **Expiry** times. +- Define **Services** by selecting **blob** and clearing other checkboxes. +- Define **Resource Type** by selecting **Container** and **Object** (clear other checkboxes). +- Make sure the **Create**, **Write**, and **List** are selected. +- Specify the signed key **Start** and **Expiry** times. - Select **Generate SAS token and URL**. - The Blob SAS token query string appears in the lower area of the window. - Copy and paste the **Blob SAS token** values into a **secure location for use in the Azure PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. -![Screenshot of SAS token on the account level - Option 2](media/SAS-token-on-the-account-level.png "SAS token on the account level - Option 2") +![Screenshot of SAS token on the account level - Option 2](media/SAS-token-on-the-account-level.png "SAS token on the account level - Option 2") ## Create an Azure Blob Data Connection in PlayFab ### Step 1: Navigate to the data connections tab -![Screenshot of PlayFab data connections tab](media/navigate-to-data-connections-tab.png "PlayFab data connections tab") +![Screenshot of PlayFab data connections tab](media/navigate-to-data-connections-tab.png "PlayFab data connections tab") - Login to PlayFab and navigate to your title. - Click on the “Data” section in the left-hand menu @@ -81,12 +81,12 @@ For PlayFab to ingest data in your storage account, container details along with | Value | Details | |:-----------|:-----------| -|Name | The friendly name of your data connection. This name will allow you to find the data connection later to edit it. Put a descriptive name here. +|Name | The friendly name of your data connection. This name will allow you to find the data connection later to edit it. Put a descriptive name here. | Account name | The Azure Storage Account. | | Container name | The Azure Storage Account Container. | | Sas token | Either the SAS token generated by the container, or the Blob SAS token query string. | -![Screenshot of configuring and ADX data connection](media/configure-new-data-connection-blob.PNG "ADX data connection configuration") +![Screenshot of configuring and ADX data connection](media/configure-new-data-connection-blob.PNG "ADX data connection configuration") > [!Note] -> We recommend using a table name that does not exist. If you use an existing table and the schema is not what PlayFab is expecting, then the schema will be modified. +> We recommend using a table name that does not exist. If you use an existing table and the schema is not what PlayFab is expecting, then the schema will be modified. From 6d198063d022218253b0dcf8afc9a6553355e1d2 Mon Sep 17 00:00:00 2001 From: foxvalo <218149361+foxvalo@users.noreply.github.com> Date: Thu, 29 Jan 2026 12:45:32 -0800 Subject: [PATCH 26/76] 60428657_clarification_language (#2787) * Link: 60428657 Context/Status: Added clarification language. Approved by antnguyen. * Fixed flagged URL. * Updated name change of community forums to community Discord. * Updated backticks line 144. --------- Co-authored-by: v-foxval@microsoft.com --- .../emails/using-a-rule-to-verify-a-contact-email-address.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/playfab-docs/live-service-management/game-configuration/title-communications/emails/using-a-rule-to-verify-a-contact-email-address.md b/playfab-docs/live-service-management/game-configuration/title-communications/emails/using-a-rule-to-verify-a-contact-email-address.md index a1e8d7706..ea1692fc2 100644 --- a/playfab-docs/live-service-management/game-configuration/title-communications/emails/using-a-rule-to-verify-a-contact-email-address.md +++ b/playfab-docs/live-service-management/game-configuration/title-communications/emails/using-a-rule-to-verify-a-contact-email-address.md @@ -141,6 +141,8 @@ void FailureCallback(PlayFabError error) } ``` +After 'AddOrUpdateContactEmail' succeeds, the com.playfab.player_updated_contact_email event triggers the rule and PlayFab sends the verification email automatically. There is no separate step to send the email. + ## Step 4 - Confirm that the contact email was added to the player's profile Next, confirm that the contact email was added to the player's profile. Log into the **Game Manager**, and visit the **Players Profile** page. @@ -219,5 +221,4 @@ When the player selects that URL, three things happen: So that's it for this tutorial. You've seen how to set up your SMTP server, create an email template, and create a rule that sends an email to a player verifying their email address. -If you have any questions or feedback on this tutorial, please let us know in our [community forums](https://community.playfab.com/). - +If you have any questions or feedback on this tutorial, please let us know in our [community Discord](https://developer.microsoft.com/en-us/games/articles/2024/05/playfab-dev-forums-move-to-discord/). \ No newline at end of file From cada583950468b01f80371f19729b13bd62bc9e9 Mon Sep 17 00:00:00 2001 From: foxvalo <218149361+foxvalo@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:22:44 -0800 Subject: [PATCH 27/76] 60428583 Unreal update (#2788) * Link: 60428583 Context/Status: Added additional information. Approved by edigonzales. * Updated language per comment. --------- Co-authored-by: v-foxval@microsoft.com --- playfab-docs/sdks/unreal/quickstart.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/playfab-docs/sdks/unreal/quickstart.md b/playfab-docs/sdks/unreal/quickstart.md index e2ff2eb0e..6d9f9b9a4 100644 --- a/playfab-docs/sdks/unreal/quickstart.md +++ b/playfab-docs/sdks/unreal/quickstart.md @@ -46,6 +46,8 @@ To enable the PlayFab Plugin: 1. From the **Settings** menu, under **Game Specific Settings** select **Plugins**. 2. Enable the **PlayFab** plugin and restart Unreal Engine as required. +If "PlayFab" doesn't appear in **Plugins**, verify that the plugin is installed from the Unreal Marketplace. Restart Unreal Editor. Then open **Plugins** again and search for "PlayFab." + ### Add PlayFab as a Module dependency in C++ In Visual Studio, add PlayFab as a module dependency in your C++ project: From 7099e585b0a6a95ae6000c2baad0da83146af91d Mon Sep 17 00:00:00 2001 From: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:31:57 -0600 Subject: [PATCH 28/76] Updates for OSS V1 UE5.7 release (#2795) * Doc updates for 5.7 support * Minor updates in formatting * Addressing format feedback --------- Co-authored-by: Raul Gomez Rodriguez --- .../party-unreal-engine-oss-overview.md | 11 ++++---- .../party-unreal-engine-oss-quickstart.md | 2 +- .../networking/unreal-release-notes.md | 27 +++++++++++++------ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-overview.md b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-overview.md index 31fb0880f..1cbab8d83 100644 --- a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-overview.md +++ b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-overview.md @@ -52,10 +52,11 @@ PlayFab OSS works alongside the PlayFab SDK marketplace plugin, which provides o | 5.3 | Supported* | Supported* | Supported* | Supported* | Supported* | Supported* | | 5.4 | Supported* | Supported* | Supported* | Supported* | Supported* | Supported* | | 5.5 | Supported* | Supported* | Supported* | Supported* | Supported* | Supported* | -| 5.6 | Supported | Supported | Supported | Supported | Supported | Supported | +| 5.6 | Supported* | Supported* | Supported* | Supported* | Supported* | Supported* | +| 5.7 | Supported | Supported | Supported | Supported | Supported | Supported | -*For users on previous versions of Unreal Engine (UE4.27, 5.0, 5.1, 5.2, 5.3, and 5.4) who wish to use PlayFab Online Subsystem, here are two options: -- Upgrade your local Unreal Engine version to 5.6. +*For users on previous versions of Unreal Engine (UE4.27, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5 and 5.6) who wish to use PlayFab Online Subsystem, here are two options: +- Upgrade your local Unreal Engine version to 5.7. - Pull the latest release and backport it to your game. For UE4, 4.27 is the recommended version since crossplay between different platforms doesn't work on 4.26, but it does on 4.27. If you're on an earlier version of Unreal Engine 4, the OSS can be backported with minimal work. See [Using older versions of Unreal Engine 4](party-unreal-engine-using-older-versions.md) for more details. @@ -81,7 +82,7 @@ The supported Nintendo Switch SDK versions can be found at [Switch SDK Updates P - UE5.0: \Engine\Platforms\Switch\Source\Programs\UnrealBuildTool\SwitchPlatformSDK.cs - UE5.1, UE5.2 and UE5.3: \Engine\Platforms\Switch\Source\Programs\UnrealBuildTool\SwitchPlatformSDK.Versions.cs - UE5.4: \Engine\Platforms\Switch\Config\Switch_SDK.json -- UE5.5 and UE5.6: \Engine\Platforms\Nintendo\Config\Nintendo_SDK.json +- UE5.5, UE5.6 and UE5.7: \Engine\Platforms\Nintendo\Config\Nintendo_SDK.json ## Which version of the PS5™ and PS4™ SDKs are supported? @@ -89,7 +90,7 @@ The supported Sony PlayStation SDK versions can be found at [PS4 SDK Compatibili - UE4: \Engine\Platforms\[PS4|PS5]\Source\Programs\UnrealBuildTool\UEBuild[PS4|PS5].cs - UE5.0: \Engine\Platforms\[PS4|PS5]\Source\Programs\UnrealBuildTool\[PS4|PS5]PlatformSDK.cs - UE5.1, UE5.2 and UE5.3: \Engine\Platforms\[PS4|PS5]\Source\Programs\UnrealBuildTool\[PS4|PS5]PlatformSDK.Versions.cs -- UE5.4, UE5.5 and UE5.6: \Engine\Platforms\[PS4|PS5]\Config\[PS4|PS5]_SDK.json +- UE5.4, UE5.5, UE5.6 and UE5.7: \Engine\Platforms\[PS4|PS5]\Config\[PS4|PS5]_SDK.json >[!NOTE] > In order to access Unreal’s documentation and UDN forum links above, you must be a registered Unreal Developer and tented for the specific platform. diff --git a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md index 4f491b96b..1776e3198 100644 --- a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md +++ b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md @@ -232,7 +232,7 @@ Ways to help you troubleshoot issues. Users might face issues when trying to create an Unreal Engine Installed Build with the OnlineSubsystemPlayFab on GDK build flavors. We provide the following guidance to successfully overcome this issue until there's a more complete solution. -**If you're using Unreal Engine 5.4, 5.5 or 5.6:** +**If you're using Unreal Engine 5.4, 5.5, 5.6 or 5.7:** * You might encounter the following runtime error: `Runtime dependency Party.dll is configured to be staged from C:\Program Files (x86)\Microsoft GDK\\Party.dll and Engine\Plugins\Online\OnlineSubsystemPlayFab\Platforms\GDK\Redist\Party.dll` * Navigate to Engine\Platforms\GDK\Plugins\Online\OnlineSubsystemGDK\ diff --git a/playfab-docs/multiplayer/networking/unreal-release-notes.md b/playfab-docs/multiplayer/networking/unreal-release-notes.md index 04d16dc12..3e5c86045 100644 --- a/playfab-docs/multiplayer/networking/unreal-release-notes.md +++ b/playfab-docs/multiplayer/networking/unreal-release-notes.md @@ -14,20 +14,31 @@ ms.localizationpriority: medium Refer to [QuickStart: PlayFab Online Subsystem (OSS)](party-unreal-engine-oss-quickstart.md) for download and install instructions. -## 2.3.7 -**Release 2.3.7 is ready to use with Unreal Engine 5.6.** +## 2.3.8 +**Release 2.3.8 is ready to use with Unreal Engine 5.7.** + +UE5.7 Upgrade Fixes: + +* Removed the unused `SEARCH_PRESENCE` key from the lobby search key mapping and related query filter logic, simplifying lobby search parameter handling. +* Removed dead code related to session search on Win64, as the new join logic no longer relies on this path. + +Bug fixes: -**Library Updates:** +* Added a new `CleanupFailedJoinSession` method to `FOnlineSessionPlayFab` to ensure proper cleanup of PlayFab and Party sessions, removal of local session references, and delegate notification when a native session join fails. This method is now called in all relevant failure paths. -Multiplayer SDK C++ library (Windows/GDK) : From 1.7.9 to 1.8.0. +* Changed logic to cache the desired session (`CachedDesiredSession`) instead of searching for it on every join, simplifying and improving the reliability of native session joins. -Party SDK C++ library (Windows/GDK) : From 1.10.5 to 1.10.12. +## 2.3.7 +**Release 2.3.7 is ready to use with Unreal Engine 5.6.** + +Library Updates: -**UE5.6 Upgrade Fixes:** +- Multiplayer SDK C++ library (Windows/GDK) : From 1.7.9 to 1.8.0. +- Party SDK C++ library (Windows/GDK) : From 1.10.5 to 1.10.12. -### Plugin Configuration Updates +UE5.6 Upgrade Fixes: -* Updated `OnlineSubsystemPlayFab.uplugin` to use `PlatformAllowList` instead of `WhitelistPlatforms`, and renamed `OnlineSubsystemSwitch` to `OnlineSubsystemNintendo` for consistency. Also incremented the plugin version. [[1]](diffhunk://#diff-5e89106b2fe67da11c76d335b2c0f6c597035a66aa80dc7021dfc24cb8ef24cfL4-R5) [[2]](diffhunk://#diff-5e89106b2fe67da11c76d335b2c0f6c597035a66aa80dc7021dfc24cb8ef24cfL27-R27) [[3]](diffhunk://#diff-5e89106b2fe67da11c76d335b2c0f6c597035a66aa80dc7021dfc24cb8ef24cfL57-R87) +* Updated `OnlineSubsystemPlayFab.uplugin` to use `PlatformAllowList` instead of `WhitelistPlatforms`, and renamed `OnlineSubsystemSwitch` to `OnlineSubsystemNintendo` for consistency. Also incremented the plugin version. * On UE 5.6 and later the `DriverClassName` parameter requires the "/Script/" prefix. For example, use `"/Script/OnlineSubsystemPlayFab.PlayFabNetDriver"` instead of `"OnlineSubsystemPlayFab.PlayFabNetDriver"`. Example usage: ``` From c6ef4b419a35d3433be701ad34562d2bb20de88c Mon Sep 17 00:00:00 2001 From: Tom Cooper <47767394+tomcoMSFT@users.noreply.github.com> Date: Fri, 6 Feb 2026 11:44:07 -0800 Subject: [PATCH 29/76] Add Party 1.10.16 release notes. (#2789) --- .../multiplayer/networking/release-notes.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/playfab-docs/multiplayer/networking/release-notes.md b/playfab-docs/multiplayer/networking/release-notes.md index 0b48370c7..f18730d59 100644 --- a/playfab-docs/multiplayer/networking/release-notes.md +++ b/playfab-docs/multiplayer/networking/release-notes.md @@ -14,12 +14,21 @@ ms.localizationpriority: medium > [!NOTE] > Support for the XDK and Windows 7 platforms ended on August 1, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using Windows 7 or XDK versions of the PlayFab Party library. -> ->For more information, please see our [forum post](https://community.playfab.com/articles/141546/playfab-party-ending-support-for-the-xdk-and-windo.html). > [!NOTE] > Support for 32-bit Android platforms (arm7 and x86) ended on October 19th, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using the PlayFab Party library on 32-bit Android platforms. +## 1.10.16 + +February 2, 2026 + +- GDK: Added support for environments that use in-proc GRTS. +- GDK: Added support for [`PartyAudioDeviceSelectionType::SystemDefault`](reference/enums/partyaudiodeviceselectiontype.md). + +### Bug fixes + +- Fixed possible crash in multinetwork transition scenarios. + ## 1.10.15 December 17, 2025 From 8b9614949e35bc125d748aa933cfb5477e182bd1 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 12:21:43 -0800 Subject: [PATCH 30/76] Add scheduled workflow to merge Main into Live on 2nd and 4th Tuesdays (#2797) * Initial plan * Add GitHub Action workflow for scheduled Main to Live merge Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> * Fix code review issues: correct comment and quote job.status Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> * Remove redundant --no-edit flag and use POSIX-compliant comparison Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> * Add explicit permissions to limit GITHUB_TOKEN scope Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> --- .github/workflows/merge-main-to-live.yml | 87 ++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 .github/workflows/merge-main-to-live.yml diff --git a/.github/workflows/merge-main-to-live.yml b/.github/workflows/merge-main-to-live.yml new file mode 100644 index 000000000..082eab245 --- /dev/null +++ b/.github/workflows/merge-main-to-live.yml @@ -0,0 +1,87 @@ +name: Merge Main to Live + +on: + schedule: + # Run at 9:00 AM UTC every Tuesday + - cron: '0 9 * * 2' + workflow_dispatch: # Allow manual trigger for testing + +jobs: + merge: + runs-on: ubuntu-latest + permissions: + contents: write # Required to push changes to the Live branch + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Check if it's 2nd or 4th Tuesday + id: check_date + run: | + # Get the current day of the month + day=$(date +%d) + # Remove leading zero if present + day=$((10#$day)) + + # Calculate which week of the month we're in (1-5) + week=$(( (day - 1) / 7 + 1 )) + + # Get the current day of week (1=Monday, 2=Tuesday, ..., 7=Sunday) + dow=$(date +%u) + + echo "Day of month: $day" + echo "Week of month: $week" + echo "Day of week: $dow" + + # Check if today is Tuesday (dow=2) and it's the 2nd or 4th week + if [ "$dow" = "2" ] && ([ "$week" = "2" ] || [ "$week" = "4" ]); then + echo "should_merge=true" >> $GITHUB_OUTPUT + echo "This is the 2nd or 4th Tuesday of the month. Proceeding with merge." + else + echo "should_merge=false" >> $GITHUB_OUTPUT + echo "Not the 2nd or 4th Tuesday. Skipping merge." + fi + + - name: Configure Git + if: steps.check_date.outputs.should_merge == 'true' + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Merge Main into Live + if: steps.check_date.outputs.should_merge == 'true' + run: | + echo "Fetching branches..." + git fetch origin Main:Main || git fetch origin main:Main + git fetch origin Live:Live || git fetch origin live:Live + + echo "Checking out Live branch..." + git checkout Live + + echo "Merging Main into Live..." + if git merge Main -m "Automated merge: Main into Live ($(date +'%Y-%m-%d'))"; then + echo "Merge successful!" + + echo "Pushing changes to Live branch..." + git push origin Live + echo "Push successful!" + else + echo "Merge conflict detected!" + echo "Please resolve conflicts manually." + git merge --abort + exit 1 + fi + + - name: Report merge status + if: always() && steps.check_date.outputs.should_merge == 'true' + run: | + if [ '${{ job.status }}' = 'success' ]; then + echo "✅ Successfully merged Main into Live branch" + else + echo "❌ Failed to merge Main into Live branch" + echo "Please check for merge conflicts and resolve them manually" + fi From 271262af9523dd19e64bb003f80d85a8c83c3ec1 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 13:59:17 -0800 Subject: [PATCH 31/76] [WIP] Update merge-main-to-live workflow for code owner approval (#2798) * Initial plan * Update merge-main-to-live workflow to create PR instead of direct merge Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> * Address code review feedback: improve branch naming and PR body readability Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> --- .github/workflows/merge-main-to-live.yml | 62 ++++++++++++++++++------ 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/.github/workflows/merge-main-to-live.yml b/.github/workflows/merge-main-to-live.yml index 082eab245..4b4a481b6 100644 --- a/.github/workflows/merge-main-to-live.yml +++ b/.github/workflows/merge-main-to-live.yml @@ -10,7 +10,8 @@ jobs: merge: runs-on: ubuntu-latest permissions: - contents: write # Required to push changes to the Live branch + contents: write # Required to create branch and PR + pull-requests: write # Required to create pull request steps: - name: Checkout repository @@ -52,36 +53,67 @@ jobs: git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - - name: Merge Main into Live + - name: Create merge branch and PR if: steps.check_date.outputs.should_merge == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | echo "Fetching branches..." git fetch origin Main:Main || git fetch origin main:Main git fetch origin Live:Live || git fetch origin live:Live - echo "Checking out Live branch..." - git checkout Live + # Create a unique branch name for this merge + BRANCH_NAME="merge-main-to-live-$(date +'%Y-%m-%d')-${{ github.run_id }}" - echo "Merging Main into Live..." - if git merge Main -m "Automated merge: Main into Live ($(date +'%Y-%m-%d'))"; then + echo "Creating merge branch from Live: $BRANCH_NAME" + git checkout -b $BRANCH_NAME Live + + echo "Merging Main into merge branch..." + if git merge Main -m "Automated merge: Main into Live ($(date +'%Y-%m-%d'))" --no-edit; then echo "Merge successful!" - echo "Pushing changes to Live branch..." - git push origin Live - echo "Push successful!" + echo "Pushing merge branch to origin..." + git push origin $BRANCH_NAME + + echo "Creating Pull Request..." + PR_BODY="This is an automated pull request to merge Main branch into Live branch. + + **Schedule:** This PR is created on the 2nd and 4th Tuesday of each month. + + **Instructions:** + - Review the changes + - Ensure all checks pass + - Code owners should approve this PR + - Merge when ready + + If there are conflicts, they will need to be resolved manually." + + gh pr create \ + --base Live \ + --head $BRANCH_NAME \ + --title "Automated merge: Main to Live ($(date +'%Y-%m-%d'))" \ + --body "$PR_BODY" + + echo "Pull request created successfully!" else - echo "Merge conflict detected!" - echo "Please resolve conflicts manually." + echo "❌ Merge conflict detected!" + echo "Cannot create PR automatically due to conflicts." + echo "Please resolve conflicts manually by:" + echo "1. Creating a branch from Live" + echo "2. Merging Main into that branch" + echo "3. Resolving conflicts" + echo "4. Creating a PR to Live" git merge --abort exit 1 fi - - name: Report merge status + - name: Report PR creation status if: always() && steps.check_date.outputs.should_merge == 'true' run: | if [ '${{ job.status }}' = 'success' ]; then - echo "✅ Successfully merged Main into Live branch" + echo "✅ Successfully created Pull Request from Main to Live branch" + echo "Code owners can now review and approve the PR" else - echo "❌ Failed to merge Main into Live branch" - echo "Please check for merge conflicts and resolve them manually" + echo "❌ Failed to create Pull Request" + echo "Please check for merge conflicts and create the PR manually" fi From e180c2acc3a5b62ff93b775973e565bfa4d4ef97 Mon Sep 17 00:00:00 2001 From: foxvalo <218149361+foxvalo@users.noreply.github.com> Date: Fri, 6 Feb 2026 14:17:14 -0800 Subject: [PATCH 32/76] 60428644_playfab_support_language_update (#2794) * 60428644_playfab_support_language_update * Updated link --------- Co-authored-by: v-foxval@microsoft.com --- playfab-docs/pricing/support.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/playfab-docs/pricing/support.md b/playfab-docs/pricing/support.md index a0e42048a..47f9373fe 100644 --- a/playfab-docs/pricing/support.md +++ b/playfab-docs/pricing/support.md @@ -73,6 +73,8 @@ Support availability is based on your account plan, with higher tiers offering e 3. To access the help menu, select the **?** in the top right navigation bar. 4. Select **Contact Us** and fill out the support form. +If you recently requested an upgrade, support ticket submission becomes available when the plan change takes effect. Plan changes are scheduled for the beginning of the next billing period. To confirm your current plan and effective date, see [Account upgrades](account-upgrades.md). + ### EMERGENCY ESCALATIONS **Purpose:** Provides 24/7 access to PlayFab's on-call engineering team in the event of critical service-impacting issues. This provides fastest incident response time to customers during emergencies. From e09847e94c3227a71e04164be02eaa82bc53fd42 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:14:14 -0800 Subject: [PATCH 33/76] Align merge-main-to-live workflow with gdk-docs-pr pattern (#2799) * Initial plan * Update merge-main-to-live workflow to use direct PR approach Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> * Fix issue label from merge-conflict to workflow-failure Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> * Align workflow structure with gdk-docs-pr pattern Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> --- .github/workflows/merge-main-to-live.yml | 223 ++++++++++++++--------- 1 file changed, 135 insertions(+), 88 deletions(-) diff --git a/.github/workflows/merge-main-to-live.yml b/.github/workflows/merge-main-to-live.yml index 4b4a481b6..c019e86b0 100644 --- a/.github/workflows/merge-main-to-live.yml +++ b/.github/workflows/merge-main-to-live.yml @@ -10,8 +10,9 @@ jobs: merge: runs-on: ubuntu-latest permissions: - contents: write # Required to create branch and PR - pull-requests: write # Required to create pull request + contents: read # Required for checking out code + pull-requests: write # Required for creating pull requests + issues: write # Required for creating issues on failure steps: - name: Checkout repository @@ -20,100 +21,146 @@ jobs: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - - name: Check if it's 2nd or 4th Tuesday + - name: Check if today is 2nd or 4th Tuesday id: check_date run: | - # Get the current day of the month - day=$(date +%d) - # Remove leading zero if present - day=$((10#$day)) + # Get current day of month + DAY=$(date +%d) + # Get day of week (1=Monday, 2=Tuesday, ..., 7=Sunday) + DOW=$(date +%u) - # Calculate which week of the month we're in (1-5) - week=$(( (day - 1) / 7 + 1 )) - - # Get the current day of week (1=Monday, 2=Tuesday, ..., 7=Sunday) - dow=$(date +%u) - - echo "Day of month: $day" - echo "Week of month: $week" - echo "Day of week: $dow" - - # Check if today is Tuesday (dow=2) and it's the 2nd or 4th week - if [ "$dow" = "2" ] && ([ "$week" = "2" ] || [ "$week" = "4" ]); then - echo "should_merge=true" >> $GITHUB_OUTPUT - echo "This is the 2nd or 4th Tuesday of the month. Proceeding with merge." + # Check if today is Tuesday (2) + if [ "$DOW" -eq 2 ]; then + # Calculate which week of the month we're in (1-5) + # Remove leading zero if present + DAY=$((10#$DAY)) + WEEK=$(( (DAY - 1) / 7 + 1 )) + + # Check if it's the 2nd or 4th Tuesday + if [ "$WEEK" -eq 2 ] || [ "$WEEK" -eq 4 ]; then + echo "is_target_tuesday=true" >> $GITHUB_OUTPUT + echo "This is the 2nd or 4th Tuesday of the month" + else + echo "is_target_tuesday=false" >> $GITHUB_OUTPUT + echo "This is not the 2nd or 4th Tuesday" + fi else - echo "should_merge=false" >> $GITHUB_OUTPUT - echo "Not the 2nd or 4th Tuesday. Skipping merge." + echo "is_target_tuesday=false" >> $GITHUB_OUTPUT + echo "Today is not Tuesday" fi - - name: Configure Git - if: steps.check_date.outputs.should_merge == 'true' - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - - name: Create merge branch and PR - if: steps.check_date.outputs.should_merge == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - echo "Fetching branches..." - git fetch origin Main:Main || git fetch origin main:Main - git fetch origin Live:Live || git fetch origin live:Live - - # Create a unique branch name for this merge - BRANCH_NAME="merge-main-to-live-$(date +'%Y-%m-%d')-${{ github.run_id }}" - - echo "Creating merge branch from Live: $BRANCH_NAME" - git checkout -b $BRANCH_NAME Live - - echo "Merging Main into merge branch..." - if git merge Main -m "Automated merge: Main into Live ($(date +'%Y-%m-%d'))" --no-edit; then - echo "Merge successful!" + - name: Check for existing PR + if: steps.check_date.outputs.is_target_tuesday == 'true' + id: check_pr + uses: actions/github-script@v7 + with: + script: | + const { data: pulls } = await github.rest.pulls.list({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + head: `${context.repo.owner}:Main`, + base: 'Live' + }); - echo "Pushing merge branch to origin..." - git push origin $BRANCH_NAME + if (pulls.length > 0) { + core.setOutput('pr_exists', 'true'); + core.setOutput('pr_number', pulls[0].number); + core.setOutput('pr_url', pulls[0].html_url); + } else { + core.setOutput('pr_exists', 'false'); + } + + - name: Create Pull Request + if: steps.check_date.outputs.is_target_tuesday == 'true' && steps.check_pr.outputs.pr_exists == 'false' + id: create_pr + uses: actions/github-script@v7 + with: + script: | + const date = new Date().toISOString().split('T')[0]; + const title = `Scheduled Merge: Main to Live on ${date}`; + const body = [ + 'This is an automated pull request to merge Main into Live branch.', + '', + `**Scheduled merge date:** ${date}`, + `**Schedule:** This PR is created on the 2nd and 4th Tuesday of each month.`, + `**Workflow run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}`, + '', + '**Instructions:**', + '- Review the changes', + '- Ensure all checks pass', + '- Code owners should approve this PR', + '- Merge when ready', + '', + 'If there are conflicts, they will need to be resolved manually.', + '', + '---', + '*This PR was automatically created by the scheduled merge workflow.*' + ].join('\n'); - echo "Creating Pull Request..." - PR_BODY="This is an automated pull request to merge Main branch into Live branch. + try { + const { data: pr } = await github.rest.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: title, + body: body, + head: 'Main', + base: 'Live' + }); + + core.setOutput('pr_number', pr.number); + core.setOutput('pr_url', pr.html_url); + console.log(`Pull request created: ${pr.html_url}`); + } catch (error) { + core.setFailed(`Failed to create pull request: ${error.message}`); + throw error; + } - **Schedule:** This PR is created on the 2nd and 4th Tuesday of each month. - - **Instructions:** - - Review the changes - - Ensure all checks pass - - Code owners should approve this PR - - Merge when ready - - If there are conflicts, they will need to be resolved manually." + - name: Comment on existing PR + if: steps.check_date.outputs.is_target_tuesday == 'true' && steps.check_pr.outputs.pr_exists == 'true' + uses: actions/github-script@v7 + env: + PR_NUMBER: ${{ steps.check_pr.outputs.pr_number }} + with: + script: | + const date = new Date().toISOString().split('T')[0]; + const prNumber = parseInt(process.env.PR_NUMBER); + const comment = [ + `♻️ Scheduled merge workflow ran again on ${date}.`, + '', + 'This PR is still open and ready for review.', + '', + `**Workflow run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}` + ].join('\n'); - gh pr create \ - --base Live \ - --head $BRANCH_NAME \ - --title "Automated merge: Main to Live ($(date +'%Y-%m-%d'))" \ - --body "$PR_BODY" + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: comment + }); - echo "Pull request created successfully!" - else - echo "❌ Merge conflict detected!" - echo "Cannot create PR automatically due to conflicts." - echo "Please resolve conflicts manually by:" - echo "1. Creating a branch from Live" - echo "2. Merging Main into that branch" - echo "3. Resolving conflicts" - echo "4. Creating a PR to Live" - git merge --abort - exit 1 - fi - - - name: Report PR creation status - if: always() && steps.check_date.outputs.should_merge == 'true' - run: | - if [ '${{ job.status }}' = 'success' ]; then - echo "✅ Successfully created Pull Request from Main to Live branch" - echo "Code owners can now review and approve the PR" - else - echo "❌ Failed to create Pull Request" - echo "Please check for merge conflicts and create the PR manually" - fi + console.log(`Comment added to existing PR #${prNumber}`); + + - name: Create Issue on Failure + if: failure() && steps.check_date.outputs.is_target_tuesday == 'true' + uses: actions/github-script@v7 + with: + script: | + const date = new Date().toISOString().split('T')[0]; + const title = `Scheduled Merge PR Creation Failed: Main to Live on ${date}`; + const body = [ + 'The scheduled merge workflow failed to create a pull request from Main to Live branch.', + '', + `**Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}`, + '', + 'Please review the workflow logs and create the pull request manually if needed.' + ].join('\n'); + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: title, + body: body, + labels: ['workflow-failure', 'automated'] + }); From 2b8149fb984987813f0012748b379608738fe92c Mon Sep 17 00:00:00 2001 From: ronnyparedesc <113482725+ronnyparedesc@users.noreply.github.com> Date: Mon, 9 Feb 2026 09:57:51 -0800 Subject: [PATCH 34/76] PlayStream documentation update AdPlacement, Addons, ApiAccessPolicy, CloudScript (#2800) * AdPlacement * Addon docs * ApiAccessPolicy * Cloudscript docs * Rename author --- .../events/Addons/title-addon-changed.md | 29 ++++++ .../title-api-settings-changed.md | 6 +- .../title-permission-policy-changed.md | 2 +- .../CloudScript/cloudscript-executed.md | 27 ++++++ .../entity-executed-cloud-script.md | 6 +- .../player-executed-cloudscript.md | 4 +- ...r-triggered-action-executed-cloudscript.md | 6 +- .../title-added-cloudscript.md | 2 +- .../title-published-cloudscript.md | 2 +- .../title-scheduled-cloudscript-executed.md | 6 +- .../data-types/addonprovisioningstate.md | 27 ++++++ playfab-docs/api-references/events/index.md | 93 +++++++++++-------- .../events/player-ad-activity-valued.md | 31 ------- 13 files changed, 153 insertions(+), 88 deletions(-) create mode 100644 playfab-docs/api-references/events/Addons/title-addon-changed.md rename playfab-docs/api-references/events/{ => ApiAccessPolicy}/title-api-settings-changed.md (66%) rename playfab-docs/api-references/events/{ => ApiAccessPolicy}/title-permission-policy-changed.md (89%) create mode 100644 playfab-docs/api-references/events/CloudScript/cloudscript-executed.md rename playfab-docs/api-references/events/{ => CloudScript}/entity-executed-cloud-script.md (66%) rename playfab-docs/api-references/events/{ => CloudScript}/player-executed-cloudscript.md (75%) rename playfab-docs/api-references/events/{ => CloudScript}/player-triggered-action-executed-cloudscript.md (70%) rename playfab-docs/api-references/events/{ => CloudScript}/title-added-cloudscript.md (91%) rename playfab-docs/api-references/events/{ => CloudScript}/title-published-cloudscript.md (88%) rename playfab-docs/api-references/events/{ => CloudScript}/title-scheduled-cloudscript-executed.md (62%) create mode 100644 playfab-docs/api-references/events/data-types/addonprovisioningstate.md delete mode 100644 playfab-docs/api-references/events/player-ad-activity-valued.md diff --git a/playfab-docs/api-references/events/Addons/title-addon-changed.md b/playfab-docs/api-references/events/Addons/title-addon-changed.md new file mode 100644 index 000000000..eee0c4985 --- /dev/null +++ b/playfab-docs/api-references/events/Addons/title-addon-changed.md @@ -0,0 +1,29 @@ +--- +title: title_addon_changed +author: ronnyparedes +description: title_addon_changed event. +ms.author: ronnyparedes +ms.date: 06/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# title_addon_changed + +This event is triggered when a marketplace AddOn is installed, or changes state. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|AddOnId|String|Unique identifier of the AddOn affected.| +|AddOnName|String|Name of the AddOn affected.| +|DeveloperId|String|Developer/Studio ID.| +|State|[AddOnProvisioningState](../data-types/addonprovisioningstate.md)|Current state of the AddOn. Values include Inactive, Paused, Active, Pending, and PendingWithError.| +|UserId|String|May be null if user is unknown (Admin API, partner source).| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-api-settings-changed.md b/playfab-docs/api-references/events/ApiAccessPolicy/title-api-settings-changed.md similarity index 66% rename from playfab-docs/api-references/events/title-api-settings-changed.md rename to playfab-docs/api-references/events/ApiAccessPolicy/title-api-settings-changed.md index 8c7339fd1..13d7309a1 100644 --- a/playfab-docs/api-references/events/title-api-settings-changed.md +++ b/playfab-docs/api-references/events/ApiAccessPolicy/title-api-settings-changed.md @@ -19,10 +19,10 @@ This event is triggered when an API Features setting is changed for the title. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |DeveloperId|String|| -|PreviousSettingsValues|[APISettings](data-types/apisettings.md)|Settings values before the change.| -|SettingsValues|[APISettings](data-types/apisettings.md)|Settings values after the change.| +|PreviousSettingsValues|[APISettings](../data-types/apisettings.md)|Settings values before the change.| +|SettingsValues|[APISettings](../data-types/apisettings.md)|Settings values after the change.| |UserId|String|| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-permission-policy-changed.md b/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md similarity index 89% rename from playfab-docs/api-references/events/title-permission-policy-changed.md rename to playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md index 2b72afa18..0434064f5 100644 --- a/playfab-docs/api-references/events/title-permission-policy-changed.md +++ b/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md @@ -25,4 +25,4 @@ This event is triggered when an update occurs to a a title's permission policies ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/CloudScript/cloudscript-executed.md b/playfab-docs/api-references/events/CloudScript/cloudscript-executed.md new file mode 100644 index 000000000..4da59a2c3 --- /dev/null +++ b/playfab-docs/api-references/events/CloudScript/cloudscript-executed.md @@ -0,0 +1,27 @@ +--- +title: cloudscript_executed +author: ronnyparedes +description: cloudscript_executed event. +ms.author: ronnyparedes +ms.date: 06/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# cloudscript_executed + +This event is triggered when a CloudScript function is executed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|The details of the execution result.| +|FunctionName|String|Name of the CloudScript function that was executed.| +|Source|String|The source that caused the function to be executed; PlayStreamV2, Task.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/entity-executed-cloud-script.md b/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md similarity index 66% rename from playfab-docs/api-references/events/entity-executed-cloud-script.md rename to playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md index fa5f5d896..1e8ad14aa 100644 --- a/playfab-docs/api-references/events/entity-executed-cloud-script.md +++ b/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md @@ -18,11 +18,11 @@ This event is optionally triggered when a CloudScript function is executed by ca |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|CloudScriptExecutionResult|[ExecuteCloudScriptResult](data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that is useful for debugging.| +|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that is useful for debugging.| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |FunctionName|String|Name of the CloudScript function that was called.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-executed-cloudscript.md b/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md similarity index 75% rename from playfab-docs/api-references/events/player-executed-cloudscript.md rename to playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md index 61018b58b..4c526f032 100644 --- a/playfab-docs/api-references/events/player-executed-cloudscript.md +++ b/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md @@ -18,10 +18,10 @@ This event is optionally triggered when a CloudScript function is executed, eith |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|CloudScriptExecutionResult|[ExecuteCloudScriptResult](data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that is useful for debugging.| +|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that is useful for debugging.| |FunctionName|String|Name of the CloudScript function that was called.| |TitleId|String|The ID of the title to which this player event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-triggered-action-executed-cloudscript.md b/playfab-docs/api-references/events/CloudScript/player-triggered-action-executed-cloudscript.md similarity index 70% rename from playfab-docs/api-references/events/player-triggered-action-executed-cloudscript.md rename to playfab-docs/api-references/events/CloudScript/player-triggered-action-executed-cloudscript.md index 84329c0f4..55cf4e3c0 100644 --- a/playfab-docs/api-references/events/player-triggered-action-executed-cloudscript.md +++ b/playfab-docs/api-references/events/CloudScript/player-triggered-action-executed-cloudscript.md @@ -18,13 +18,13 @@ This event is triggered when a CloudScript function is run as the result of a Pl |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|CloudScriptExecutionResult|[ExecuteCloudScriptResult](data-types/executecloudscriptresult.md)|Result of the CloudScript function, including an error information. Useful for debugging.| +|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including an error information. Useful for debugging.| |FunctionName|String|Name of the CloudScript function that was called.| |TitleId|String|The ID of the title to which this player event applies.| |TriggeringEventData|object|The full JSON data of the event that triggered this CloudScript function to run. Useful for debugging.| |TriggeringEventName|String|Name of the event that triggered this CloudScript function to run.| -|TriggeringPlayer|[PlayerProfile](data-types/playerprofile.md)|JSON data profile of the player that triggered this CloudScript function to run.| +|TriggeringPlayer|[PlayerProfile](../data-types/playerprofile.md)|JSON data profile of the player that triggered this CloudScript function to run.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-added-cloudscript.md b/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md similarity index 91% rename from playfab-docs/api-references/events/title-added-cloudscript.md rename to playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md index 97c9c07f9..bc7b41782 100644 --- a/playfab-docs/api-references/events/title-added-cloudscript.md +++ b/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md @@ -27,4 +27,4 @@ This event is triggered when new CloudScript is uploaded to PlayFab. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-published-cloudscript.md b/playfab-docs/api-references/events/CloudScript/title-published-cloudscript.md similarity index 88% rename from playfab-docs/api-references/events/title-published-cloudscript.md rename to playfab-docs/api-references/events/CloudScript/title-published-cloudscript.md index fa69a854b..ef282187f 100644 --- a/playfab-docs/api-references/events/title-published-cloudscript.md +++ b/playfab-docs/api-references/events/CloudScript/title-published-cloudscript.md @@ -24,4 +24,4 @@ An inactive revision of CloudScript has been made into the active 'live' version ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-scheduled-cloudscript-executed.md b/playfab-docs/api-references/events/CloudScript/title-scheduled-cloudscript-executed.md similarity index 62% rename from playfab-docs/api-references/events/title-scheduled-cloudscript-executed.md rename to playfab-docs/api-references/events/CloudScript/title-scheduled-cloudscript-executed.md index 21afe10bc..bf3e55063 100644 --- a/playfab-docs/api-references/events/title-scheduled-cloudscript-executed.md +++ b/playfab-docs/api-references/events/CloudScript/title-scheduled-cloudscript-executed.md @@ -18,10 +18,10 @@ This event is triggered when a CloudScript function is run by a scheduled task. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|CloudScriptExecutionResult|[ExecuteCloudScriptResult](data-types/executecloudscriptresult.md)|Result of the CloudScript function, including an error information. Useful for debugging.| +|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including an error information. Useful for debugging.| |FunctionName|String|Name of the CloudScript function that was called.| -|ScheduledTask|[NameId](data-types/nameid.md)|Scheduled task that called the CloudScript| +|ScheduledTask|[NameId](../data-types/nameid.md)|Scheduled task that called the CloudScript| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/data-types/addonprovisioningstate.md b/playfab-docs/api-references/events/data-types/addonprovisioningstate.md new file mode 100644 index 000000000..7de52da43 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/addonprovisioningstate.md @@ -0,0 +1,27 @@ +--- +title: AddOnProvisioningState +author: playfab +description: AddOnProvisioningState data type. +ms.author: playfab +ms.date: 01/27/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# AddOnProvisioningState + +Represents the provisioning state of an AddOn. + +## Values + +|Value|Description| +| :--------------------|:----------------------| +|Inactive|The AddOn is inactive.| +|Active|The AddOn is active.| +|Pending|The AddOn is pending provisioning.| +|PendingWithError|The AddOn is pending with an error.| +|Paused|The AddOn is paused.| +|Waitlist|The AddOn is on a waitlist.| +|Unknown|None of the above states.| diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index dcad1ba89..83cc2b3fe 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -16,14 +16,64 @@ These are the built-in PlayStream events which are automatically generated by Pl Each event type has a set of properties that are included as part of event's data wherever it is sent. You can view these properties and build rules for triggering actions based on their values in the PlayStream tab of the Game Manager. +## AdPlacement + +- [player_ad_closed](player-ad-closed.md) + This event is triggered when a player closes an ad. + +- [player_ad_ended](player-ad-ended.md) + This event is triggered when a player finishes an ad. + +- [player_ad_opened](player-ad-opened.md) + This event is triggered when a player opens an ad. + +- [player_ad_rewarded](player-ad-rewarded.md) + This event is triggered when a player recieves an ad reward. + +- [player_ad_started](player-ad-started.md) + This event is triggered when a player starts an ad. + +## Addons + +- [title_addon_changed](Addons/title-addon-changed.md) + This event is triggered when a title addon is changed. + +## ApiAccessPolicy + +- [title_api_settings_changed](ApiAccessPolicy/title-api-settings-changed.md) + This event is triggered when an API Features setting is changed for the title. + +- [title_permission_policy_changed](ApiAccessPolicy/title-permission-policy-changed.md) + This event is triggered when an update occurs to a a title's permission policies. + +## CloudScript + +- [entity_executed_cloud_script](CloudScript/entity-executed-cloud-script.md) + This event is optionally triggered when an Entity CloudScript function is executed, either by calling the ExecuteCloudScript API with the GeneratePlayStreamEvent option or triggered by a PlayStream event action with the 'Publish results as a PlayStream Event' box checked. + +- [player_executed_cloudscript](CloudScript/player-executed-cloudscript.md) + This event is optionally triggered when a CloudScript function is executed, either by calling the ExecuteCloudScript API with the GeneratePlayStreamEvent option or triggered by a PlayStream event action with the 'Publish results as a PlayStream Event' box checked. + +- [player_triggered_action_executed_cloudscript](CloudScript/player-triggered-action-executed-cloudscript.md) + This event is triggered when a CloudScript function is run as the result of a PlayStream action, and the 'Publish results as a PlayStream Event' box was checked. + +- [title_added_cloudscript](CloudScript/title-added-cloudscript.md) + This event is triggered when new CloudScript is uploaded to PlayFab. + +- [title_published_cloudscript](CloudScript/title-published-cloudscript.md) + An inactive revision of CloudScript has been made into the active 'live' version. + +- [title_scheduled_cloudscript_executed](CloudScript/title-scheduled-cloudscript-executed.md) + This event is triggered when a CloudScript function is run by a scheduled task. + +- [cloudscript_executed](CloudScript/cloudscript-executed.md) + This event is triggered when a CloudScript function is executed. + ## General - [entity_created](entity-created.md) This event is triggered when an entity is created. -- [entity_executed_cloud_script](entity-executed-cloud-script.md) - This event is optionally triggered when an Entity CloudScript function is executed, either by calling the ExecuteCloudScript API with the GeneratePlayStreamEvent option or triggered by a PlayStream event action with the 'Publish results as a PlayStream Event' box checked. - - [entity_files_set](entity-files-set.md) This event is triggered when files are attached to an entity. @@ -281,26 +331,10 @@ Each event type has a set of properties that are included as part of event's dat - [player_ad_campaign_attribution](player-ad-campaign-attribution.md) This event is triggered by an attribution tracking Add-on when a player is matched to a paid acquisition campaign. -- [player_ad_closed](player-ad-closed.md) - This event is triggered when a player closes an ad. - - [player_added_title](player-added-title.md) This event is triggered when a player creates a new account for a title. Note: this event is triggered once per title rather than once per publisher. -- [player_ad_ended](player-ad-ended.md) - This event is triggered when a player finishes an ad. - -- [player_ad_opened](player-ad-opened.md) - This event is triggered when a player opens an ad. -- [player_ad_rewarded](player-ad-rewarded.md) - This event is triggered when a player recieves an ad reward. - -- [player_ad_activity_valued](player-ad-activity-valued.md) - Event triggered when reported value of ad view is recorded - -- [player_ad_started](player-ad-started.md) - This event is triggered when a player starts an ad. - [player_banned](player-banned.md) This event is triggered when a player is banned. @@ -326,9 +360,6 @@ Each event type has a set of properties that are included as part of event's dat - [player_displayname_changed](player-displayname-changed.md) This event is triggered when a player's display name is changed. -- [player_executed_cloudscript](player-executed-cloudscript.md) - This event is optionally triggered when a CloudScript function is executed, either by calling the ExecuteCloudScript API with the GeneratePlayStreamEvent option or triggered by a PlayStream event action with the 'Publish results as a PlayStream Event' box checked. - - [player_inventory_item_added](player-inventory-item-added.md) This event is triggered when an item is granted to a player. @@ -383,9 +414,6 @@ Each event type has a set of properties that are included as part of event's dat - [player_tag_removed](player-tag-removed.md) This event is triggered when a tag is removed from a player profile. -- [player_triggered_action_executed_cloudscript](player-triggered-action-executed-cloudscript.md) - This event is triggered when a CloudScript function is run as the result of a PlayStream action, and the 'Publish results as a PlayStream Event' box was checked. - - [player_unlinked_account](player-unlinked-account.md) This event is triggered when an authentication method is unlinked from a player's account. @@ -420,12 +448,6 @@ Each event type has a set of properties that are included as part of event's dat - [title_aborted_task](title-aborted-task.md) This event is triggered when a task instance is aborted. -- [title_added_cloudscript](title-added-cloudscript.md) - This event is triggered when new CloudScript is uploaded to PlayFab. - -- [title_api_settings_changed](title-api-settings-changed.md) - This event is triggered when an API Features setting is changed for the title. - - [title_catalog_updated](title-catalog-updated.md) This event is triggered when a catalog is changed. @@ -459,15 +481,9 @@ Each event type has a set of properties that are included as part of event's dat - [title_news_updated](title-news-updated.md) This event is triggered when a title news is created or updated. -- [title_permission_policy_changed](title-permission-policy-changed.md) - This event is triggered when an update occurs to a a title's permission policies. - - [title_profile_view_constraints_changed](title-profile-view-constraints-changed.md) This event is triggered when a profile view constraint is changed for the title. -- [title_published_cloudscript](title-published-cloudscript.md) - An inactive revision of CloudScript has been made into the active 'live' version. - - [title_queue_config_updated](title-queue-config-updated.md) This event is triggered when a queue config is changed. @@ -477,9 +493,6 @@ Each event type has a set of properties that are included as part of event's dat - [title_saved_survey](title-saved-survey.md) This event is triggered when a game's survey is saved. -- [title_scheduled_cloudscript_executed](title-scheduled-cloudscript-executed.md) - This event is triggered when a CloudScript function is run by a scheduled task. - - [title_secret_key_changed](title-secret-key-changed.md) This event is triggered when a title adds or updates a Secret Key diff --git a/playfab-docs/api-references/events/player-ad-activity-valued.md b/playfab-docs/api-references/events/player-ad-activity-valued.md deleted file mode 100644 index a626afc31..000000000 --- a/playfab-docs/api-references/events/player-ad-activity-valued.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: player_ad_activity_valued -author: joannaleecy -description: player_ad_activity_valued event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_ad_activity_valued - -Event triggered when reported value of ad view is recorded - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|AdPlacementId|String|Id of the placement| -|AdPlacementName|String|Name of the placement| -|AdUnit|String|Ad unit type| -|RevenueShare|double|Share of the revenue for this ad view (calculated as total revenue for placement divided by total views for that placement in that time window)| -|RewardId|String|Id of the reward| -|RewardName|String|Name of the reward| -|TitleId|String|The ID of the title to which this player event applies.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] From 5ac4eac28c4b35a1a4bd250dfba3c45ca9a41d0a Mon Sep 17 00:00:00 2001 From: Ernesto Cortes Groman Date: Tue, 10 Feb 2026 07:42:44 -0800 Subject: [PATCH 35/76] Revise API rate limits for inventory and redemption (#2802) --- .../economy-monetization/economy-v2/limits.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/playfab-docs/economy-monetization/economy-v2/limits.md b/playfab-docs/economy-monetization/economy-v2/limits.md index 51025a9be..cc9e76e92 100644 --- a/playfab-docs/economy-monetization/economy-v2/limits.md +++ b/playfab-docs/economy-monetization/economy-v2/limits.md @@ -69,8 +69,8 @@ The purpose of this guide is to detail the limits that are enforced when creatin | **API** | **Limit (Player)** | **Limit (Title)** | |---------|--------------------|-------------------| -| **GetInventoryItems** | 1.67 rps (100 in 60 seconds) | - | -| **GetInventoryCollectionIds** | 1.67 rps (100 in 60 seconds) | - | +| **GetInventoryItems** | 0.67 rps (40 in 60 seconds) | - | +| **GetInventoryCollectionIds** | 0.08 rps (5 in 60 seconds) | - | ### Read Transaction History @@ -82,25 +82,25 @@ The purpose of this guide is to detail the limits that are enforced when creatin | **API** | **Limit (Player)** | **Limit (Title)** | |---------|--------------------|-------------------| -| **AddInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **SubtractInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **UpdateInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **PurchaseInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **TransferInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **DeleteInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **ExecuteInventoryOperations** | 0.66 rps (60 in 90 seconds) | - | -| **DeleteInventoryCollection** | 0.16 rps (15 in 90 seconds) | - | +| **AddInventoryItems** | 0.33 rps (20 in 60 seconds) | - | +| **SubtractInventoryItems** | 0.33 rps (20 in 60 seconds) | - | +| **UpdateInventoryItems** | 0.33 rps (20 in 60 seconds) | - | +| **PurchaseInventoryItems** | 0.33 rps (20 in 60 seconds) | - | +| **TransferInventoryItems** | 0.33 rps (20 in 60 seconds) | - | +| **DeleteInventoryItems** | 0.33 rps (20 in 60 seconds) | - | +| **ExecuteInventoryOperations** | 0.33 rps (20 in 60 seconds) | - | +| **DeleteInventoryCollection** | 0.08 rps (5 in 60 seconds) | - | ### Redeem | **API** | **Limit (Player)** | **Limit (Title)** | |---------|--------------------|-------------------| -| **RedeemAppleAppStoreInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **RedeemGooglePlayInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **RedeemMicrosoftStoreInventorItems** | 0.66 rps (60 in 90 seconds) | - | -| **RedeemNintendoEShopInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **RedeemPlayStationStoreInventoryItems** | 0.66 rps (60 in 90 seconds) | - | -| **RedeemSteamInventoryItems** | 0.66 rps (60 in 90 seconds) | - | +| **RedeemAppleAppStoreInventoryItems** | 0.16 rps (10 in 60 seconds) | - | +| **RedeemGooglePlayInventoryItems** | 0.16 rps (10 in 60 seconds) | - | +| **RedeemMicrosoftStoreInventorItems** | 0.16 rps (10 in 60 seconds) | - | +| **RedeemNintendoEShopInventoryItems** | 0.16 rps (10 in 60 seconds) | - | +| **RedeemPlayStationStoreInventoryItems** | 0.16 rps (10 in 60 seconds) | - | +| **RedeemSteamInventoryItems** | 0.16 rps (10 in 60 seconds) | - | ## API Limits From 7204c33c08568b035c62f64c0b619b30d8da8130 Mon Sep 17 00:00:00 2001 From: ronnyparedesc <113482725+ronnyparedesc@users.noreply.github.com> Date: Tue, 10 Feb 2026 10:12:37 -0800 Subject: [PATCH 36/76] PlayStream event documentation update Extensions, Functions, Groups, Telemetry, Title Communications (#2803) * Extensions * Functions * Groups * Telemetry * TitleCom --- .../events/Extension/export-completed.md | 30 +++ .../{ => Extension}/title-aborted-task.md | 2 +- .../{ => Extension}/title-completed-task.md | 4 +- .../{ => Extension}/title-created-task.md | 4 +- .../{ => Extension}/title-deleted-task.md | 4 +- .../{ => Extension}/title-exceeded-limit.md | 4 +- .../{ => Extension}/title-limit-changed.md | 4 +- .../{ => Extension}/title-started-task.md | 4 +- .../{ => Extension}/title-updated-task.md | 4 +- .../events/Functions/function-executed.md | 29 +++ .../events/Functions/function-registered.md | 25 +++ .../events/Functions/function-unregistered.md | 25 +++ ...ayer-triggered-action-executed-function.md | 30 +++ .../title-scheduled-function-executed.md | 27 +++ .../events/{ => Groups}/group-created.md | 4 +- .../{ => Groups}/group-members-added.md | 6 +- .../{ => Groups}/group-members-removed.md | 6 +- .../events/{ => Groups}/group-role-created.md | 4 +- .../events/{ => Groups}/group-role-deleted.md | 4 +- .../{ => Groups}/group-role-members-added.md | 6 +- .../group-role-members-removed.md | 6 +- .../events/{ => Groups}/group-role-updated.md | 8 +- .../events/{ => Groups}/group-updated.md | 8 +- .../events/Groups/members-added.md | 27 +++ .../events/Groups/members-removed.md | 27 +++ .../events/Groups/members-role-updated.md | 28 +++ .../Groups/player-updated-membership.md | 31 +++ .../events/Groups/role-updated.md | 28 +++ .../events/Telemetry/apikey-activated.md | 29 +++ .../events/Telemetry/apikey-created.md | 29 +++ .../events/Telemetry/apikey-deactivated.md | 29 +++ .../events/Telemetry/apikey-deleted.md | 29 +++ .../events/TitleCommunications/email-sent.md | 29 +++ .../player-registered-push-notifications.md | 4 +- .../push-notification-sent.md | 28 +++ .../{ => TitleCommunications}/sent-email.md | 10 +- .../sent-push-notification.md | 2 +- .../data-types/apikeyactivatedpayload.md | 17 ++ .../events/data-types/apikeycreatedpayload.md | 18 ++ .../data-types/apikeydeactivatedpayload.md | 17 ++ .../events/data-types/apikeydeletedpayload.md | 17 ++ .../events/data-types/artifact.md | 23 +++ .../data-types/eventexportcompletionstatus.md | 22 +++ .../data-types/executefunctionresult.md | 26 +++ .../api-references/events/group-deleted.md | 30 --- playfab-docs/api-references/events/index.md | 177 ++++++++++++------ 46 files changed, 788 insertions(+), 137 deletions(-) create mode 100644 playfab-docs/api-references/events/Extension/export-completed.md rename playfab-docs/api-references/events/{ => Extension}/title-aborted-task.md (87%) rename playfab-docs/api-references/events/{ => Extension}/title-completed-task.md (78%) rename playfab-docs/api-references/events/{ => Extension}/title-created-task.md (72%) rename playfab-docs/api-references/events/{ => Extension}/title-deleted-task.md (73%) rename playfab-docs/api-references/events/{ => Extension}/title-exceeded-limit.md (82%) rename playfab-docs/api-references/events/{ => Extension}/title-limit-changed.md (85%) rename playfab-docs/api-references/events/{ => Extension}/title-started-task.md (81%) rename playfab-docs/api-references/events/{ => Extension}/title-updated-task.md (74%) create mode 100644 playfab-docs/api-references/events/Functions/function-executed.md create mode 100644 playfab-docs/api-references/events/Functions/function-registered.md create mode 100644 playfab-docs/api-references/events/Functions/function-unregistered.md create mode 100644 playfab-docs/api-references/events/Functions/player-triggered-action-executed-function.md create mode 100644 playfab-docs/api-references/events/Functions/title-scheduled-function-executed.md rename playfab-docs/api-references/events/{ => Groups}/group-created.md (80%) rename playfab-docs/api-references/events/{ => Groups}/group-members-added.md (70%) rename playfab-docs/api-references/events/{ => Groups}/group-members-removed.md (66%) rename playfab-docs/api-references/events/{ => Groups}/group-role-created.md (83%) rename playfab-docs/api-references/events/{ => Groups}/group-role-deleted.md (83%) rename playfab-docs/api-references/events/{ => Groups}/group-role-members-added.md (71%) rename playfab-docs/api-references/events/{ => Groups}/group-role-members-removed.md (71%) rename playfab-docs/api-references/events/{ => Groups}/group-role-updated.md (69%) rename playfab-docs/api-references/events/{ => Groups}/group-updated.md (64%) create mode 100644 playfab-docs/api-references/events/Groups/members-added.md create mode 100644 playfab-docs/api-references/events/Groups/members-removed.md create mode 100644 playfab-docs/api-references/events/Groups/members-role-updated.md create mode 100644 playfab-docs/api-references/events/Groups/player-updated-membership.md create mode 100644 playfab-docs/api-references/events/Groups/role-updated.md create mode 100644 playfab-docs/api-references/events/Telemetry/apikey-activated.md create mode 100644 playfab-docs/api-references/events/Telemetry/apikey-created.md create mode 100644 playfab-docs/api-references/events/Telemetry/apikey-deactivated.md create mode 100644 playfab-docs/api-references/events/Telemetry/apikey-deleted.md create mode 100644 playfab-docs/api-references/events/TitleCommunications/email-sent.md rename playfab-docs/api-references/events/{ => TitleCommunications}/player-registered-push-notifications.md (74%) create mode 100644 playfab-docs/api-references/events/TitleCommunications/push-notification-sent.md rename playfab-docs/api-references/events/{ => TitleCommunications}/sent-email.md (81%) rename playfab-docs/api-references/events/{ => TitleCommunications}/sent-push-notification.md (94%) create mode 100644 playfab-docs/api-references/events/data-types/apikeyactivatedpayload.md create mode 100644 playfab-docs/api-references/events/data-types/apikeycreatedpayload.md create mode 100644 playfab-docs/api-references/events/data-types/apikeydeactivatedpayload.md create mode 100644 playfab-docs/api-references/events/data-types/apikeydeletedpayload.md create mode 100644 playfab-docs/api-references/events/data-types/artifact.md create mode 100644 playfab-docs/api-references/events/data-types/eventexportcompletionstatus.md create mode 100644 playfab-docs/api-references/events/data-types/executefunctionresult.md delete mode 100644 playfab-docs/api-references/events/group-deleted.md diff --git a/playfab-docs/api-references/events/Extension/export-completed.md b/playfab-docs/api-references/events/Extension/export-completed.md new file mode 100644 index 000000000..4dda3453e --- /dev/null +++ b/playfab-docs/api-references/events/Extension/export-completed.md @@ -0,0 +1,30 @@ +--- +title: export_completed +author: ronnyparedes +description: export_completed event. +ms.author: ronnyparedes +ms.date: 09/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# export_completed + +This event is triggered when an export operation is completed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Artifacts|[Artifact](../data-types/artifact.md)[]|An array of artifact objects representing the exported files or resources.| +|FailureReason|String|The reason for the export failure, if the export did not succeed.| +|Id|String|The unique identifier for this export operation.| +|Name|String|The name of the export operation.| +|StartTime|DateTime|The timestamp when the export operation started.| +|Status|[EventExportCompletionStatus](../data-types/eventexportcompletionstatus.md)|The status of the export operation indicating whether it succeeded, failed, or was cancelled.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/title-aborted-task.md b/playfab-docs/api-references/events/Extension/title-aborted-task.md similarity index 87% rename from playfab-docs/api-references/events/title-aborted-task.md rename to playfab-docs/api-references/events/Extension/title-aborted-task.md index 3028d3c2d..af0b74882 100644 --- a/playfab-docs/api-references/events/title-aborted-task.md +++ b/playfab-docs/api-references/events/Extension/title-aborted-task.md @@ -24,4 +24,4 @@ This event is triggered when a task instance is aborted. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-completed-task.md b/playfab-docs/api-references/events/Extension/title-completed-task.md similarity index 78% rename from playfab-docs/api-references/events/title-completed-task.md rename to playfab-docs/api-references/events/Extension/title-completed-task.md index bb56acf98..01a0be65a 100644 --- a/playfab-docs/api-references/events/title-completed-task.md +++ b/playfab-docs/api-references/events/Extension/title-completed-task.md @@ -20,11 +20,11 @@ This event is triggered when a scheduled task has completed | :--------------------|:-------------------|:----------------------| |AbortedAt|DateTime|Timestamp on when the task was aborted. Null if task never was aborted.| |IsAborted|Boolean|Whether the task was aborted.| -|Result|[TaskInstanceStatus](data-types/taskinstancestatus.md)|Result of the task run, whether it has succeeded, failed or aborted.| +|Result|[TaskInstanceStatus](../data-types/taskinstancestatus.md)|Result of the task run, whether it has succeeded, failed or aborted.| |Summary|object|Summary of the task run. Different task types have different summary structure.| |TaskInstanceId|String|ID of the running instance of the task| |TaskType|String|Type of the scheduled task| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-created-task.md b/playfab-docs/api-references/events/Extension/title-created-task.md similarity index 72% rename from playfab-docs/api-references/events/title-created-task.md rename to playfab-docs/api-references/events/Extension/title-created-task.md index 40414e40f..baa3a757f 100644 --- a/playfab-docs/api-references/events/title-created-task.md +++ b/playfab-docs/api-references/events/Extension/title-created-task.md @@ -19,8 +19,8 @@ This event is triggered when a task is created. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |DeveloperId|String|| -|ScheduledTask|[NameIdentifier](data-types/nameidentifier.md)|Identity of the scheduled task| +|ScheduledTask|[NameIdentifier](../data-types/nameidentifier.md)|Identity of the scheduled task| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-deleted-task.md b/playfab-docs/api-references/events/Extension/title-deleted-task.md similarity index 73% rename from playfab-docs/api-references/events/title-deleted-task.md rename to playfab-docs/api-references/events/Extension/title-deleted-task.md index b78f70b6b..562a0e672 100644 --- a/playfab-docs/api-references/events/title-deleted-task.md +++ b/playfab-docs/api-references/events/Extension/title-deleted-task.md @@ -19,10 +19,10 @@ This event is triggered when a task is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |DeveloperId|String|| -|ScheduledTask|[NameIdentifier](data-types/nameidentifier.md)|Identity of the scheduled task| +|ScheduledTask|[NameIdentifier](../data-types/nameidentifier.md)|Identity of the scheduled task| |UserId|String|| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-exceeded-limit.md b/playfab-docs/api-references/events/Extension/title-exceeded-limit.md similarity index 82% rename from playfab-docs/api-references/events/title-exceeded-limit.md rename to playfab-docs/api-references/events/Extension/title-exceeded-limit.md index c8163f111..25a501a11 100644 --- a/playfab-docs/api-references/events/title-exceeded-limit.md +++ b/playfab-docs/api-references/events/Extension/title-exceeded-limit.md @@ -22,9 +22,9 @@ This event is triggered when a title exceeds a service limit and receives an err |LimitDisplayName|String|The display name of the limit that was exceeded.| |LimitId|String|The unique identifier of the limit that was exceeded.| |LimitValue|double|The limit value that was exceeded.| -|Unit|[MetricUnit](data-types/metricunit.md)|The unit of the limit that was exceeded.| +|Unit|[MetricUnit](../data-types/metricunit.md)|The unit of the limit that was exceeded.| |Value|double|The value that exceeded the limit.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-limit-changed.md b/playfab-docs/api-references/events/Extension/title-limit-changed.md similarity index 85% rename from playfab-docs/api-references/events/title-limit-changed.md rename to playfab-docs/api-references/events/Extension/title-limit-changed.md index 0ff09a6df..5bed689a0 100644 --- a/playfab-docs/api-references/events/title-limit-changed.md +++ b/playfab-docs/api-references/events/Extension/title-limit-changed.md @@ -24,9 +24,9 @@ This event is triggered when a title changes a service limit. |PreviousValue|double|The limit value before the change, if any.| |PriceUSD|double|The price of the limit level in US Dollars, if any.| |TransactionId|String|The unique identifier of the limit change transaction.| -|Unit|[MetricUnit](data-types/metricunit.md)|The unit of the limit that changed.| +|Unit|[MetricUnit](../data-types/metricunit.md)|The unit of the limit that changed.| |Value|double|The limit value after the change, if any.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-started-task.md b/playfab-docs/api-references/events/Extension/title-started-task.md similarity index 81% rename from playfab-docs/api-references/events/title-started-task.md rename to playfab-docs/api-references/events/Extension/title-started-task.md index f01f3ec40..a9ffb5cc3 100644 --- a/playfab-docs/api-references/events/title-started-task.md +++ b/playfab-docs/api-references/events/Extension/title-started-task.md @@ -21,11 +21,11 @@ This event is triggered when a task is scheduled to run. |DeveloperId|String|| |Parameter|object|Parameter of the scheduled task| |ScheduledByUserId|String|ID of user who manually scheduled the task, null if scheduled automatically| -|ScheduledTask|[NameIdentifier](data-types/nameidentifier.md)|Identity of the scheduled task| +|ScheduledTask|[NameIdentifier](../data-types/nameidentifier.md)|Identity of the scheduled task| |TaskInstanceId|String|ID of the running instance of the task| |TaskType|String|Type of the scheduled task| |UserId|String|| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-updated-task.md b/playfab-docs/api-references/events/Extension/title-updated-task.md similarity index 74% rename from playfab-docs/api-references/events/title-updated-task.md rename to playfab-docs/api-references/events/Extension/title-updated-task.md index b533193d5..603940b6f 100644 --- a/playfab-docs/api-references/events/title-updated-task.md +++ b/playfab-docs/api-references/events/Extension/title-updated-task.md @@ -20,9 +20,9 @@ This event is triggered when a task is updated. | :--------------------|:-------------------|:----------------------| |DeveloperId|String|| |HasRenamed|Boolean|| -|ScheduledTask|[NameIdentifier](data-types/nameidentifier.md)|Identity of the scheduled task| +|ScheduledTask|[NameIdentifier](../data-types/nameidentifier.md)|Identity of the scheduled task| |UserId|String|| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/Functions/function-executed.md b/playfab-docs/api-references/events/Functions/function-executed.md new file mode 100644 index 000000000..73095f966 --- /dev/null +++ b/playfab-docs/api-references/events/Functions/function-executed.md @@ -0,0 +1,29 @@ +--- +title: function_executed +author: joannaleecy +description: function_executed event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# function_executed + +This event is triggered when a CloudScript function is executed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ExecutionTimeMilliseconds|int|The execution time of the function in milliseconds.| +|FunctionName|String|The name of the function that was executed.| +|Result|[ExecuteFunctionResult](../data-types/executefunctionresult.md)|The result returned by the function execution.| +|ResultTooLarge|Boolean|Indicates if the result was too large to return and was truncated.| +|Source|String|The source or trigger that caused the function to execute.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Functions/function-registered.md b/playfab-docs/api-references/events/Functions/function-registered.md new file mode 100644 index 000000000..238697ce6 --- /dev/null +++ b/playfab-docs/api-references/events/Functions/function-registered.md @@ -0,0 +1,25 @@ +--- +title: function_registered +author: joannaleecy +description: function_registered event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# function_registered + +This event is triggered when a CloudScript function is registered. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|FunctionName|String|The name of the function that was registered.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Functions/function-unregistered.md b/playfab-docs/api-references/events/Functions/function-unregistered.md new file mode 100644 index 000000000..a75e9db6a --- /dev/null +++ b/playfab-docs/api-references/events/Functions/function-unregistered.md @@ -0,0 +1,25 @@ +--- +title: function_unregistered +author: joannaleecy +description: function_unregistered event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# function_unregistered + +This event is triggered when a CloudScript function is unregistered. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|FunctionName|String|The name of the function that was unregistered.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Functions/player-triggered-action-executed-function.md b/playfab-docs/api-references/events/Functions/player-triggered-action-executed-function.md new file mode 100644 index 000000000..42cbf7518 --- /dev/null +++ b/playfab-docs/api-references/events/Functions/player-triggered-action-executed-function.md @@ -0,0 +1,30 @@ +--- +title: player_triggered_action_executed_function +author: joannaleecy +description: player_triggered_action_executed_function event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_triggered_action_executed_function + +This event is triggered when a CloudScript Azure Function is run as the result of a PlayStream action, and the 'Publish results as a PlayStream Event' box was checked. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|FunctionExecutionResult|[ExecuteFunctionResult](../data-types/executefunctionresult.md)|Result of the CloudScript Azure Function.| +|FunctionName|String|Name of the CloudScript Azure Function that was called.| +|TriggeringEventData|Object|The full JSON data of the event that triggered this CloudScript function to run. Useful for debugging.| +|TriggeringEventName|String|Name of the event that triggered this CloudScript function to run.| +|TriggeringPlayer|[PlayerProfile](../data-types/playerprofile.md)|JSON data profile of the player that triggered this CloudScript function to run.| +|TitleId|String|The ID of the title to which this player event applies.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Functions/title-scheduled-function-executed.md b/playfab-docs/api-references/events/Functions/title-scheduled-function-executed.md new file mode 100644 index 000000000..4da6bd7bf --- /dev/null +++ b/playfab-docs/api-references/events/Functions/title-scheduled-function-executed.md @@ -0,0 +1,27 @@ +--- +title: title_scheduled_function_executed +author: joannaleecy +description: title_scheduled_function_executed event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# title_scheduled_function_executed + +This event is triggered when a scheduled CloudScript function is executed for a title. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|FunctionExecutionResult|[ExecuteFunctionResult](../data-types/executefunctionresult.md)|The result returned from executing the scheduled function.| +|FunctionName|String|The name of the scheduled function that was executed.| +|ScheduledTask|[NameId](../data-types/nameid.md)|The scheduled task that triggered this function execution.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-created.md b/playfab-docs/api-references/events/Groups/group-created.md similarity index 80% rename from playfab-docs/api-references/events/group-created.md rename to playfab-docs/api-references/events/Groups/group-created.md index a61006e88..9f9683c83 100644 --- a/playfab-docs/api-references/events/group-created.md +++ b/playfab-docs/api-references/events/Groups/group-created.md @@ -21,10 +21,10 @@ This event is triggered when an entity group is created. |CreatorEntityId|String|The identifier for the entity that created the group to which this event applies.| |CreatorEntityType|String|The type of entity that created the group to which this event applies.| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |GroupName|String|The name of the group to which this event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-members-added.md b/playfab-docs/api-references/events/Groups/group-members-added.md similarity index 70% rename from playfab-docs/api-references/events/group-members-added.md rename to playfab-docs/api-references/events/Groups/group-members-added.md index 324a667df..33d5eda4c 100644 --- a/playfab-docs/api-references/events/group-members-added.md +++ b/playfab-docs/api-references/events/Groups/group-members-added.md @@ -19,13 +19,13 @@ This event is triggered when a member is added to an entity group. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |GroupName|String|The name of the group to which this event applies.| -|Members|[Member](data-types/member.md)|The list of entities that were added to the group and role to which this event applies.| +|Members|[Member](../data-types/member.md)|The list of entities that were added to the group and role to which this event applies.| |RoleId|String|The role ID of the role to which this event applies.| |RoleName|String|The display name of the role to which this event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-members-removed.md b/playfab-docs/api-references/events/Groups/group-members-removed.md similarity index 66% rename from playfab-docs/api-references/events/group-members-removed.md rename to playfab-docs/api-references/events/Groups/group-members-removed.md index 8b4e06fc4..2185c99c0 100644 --- a/playfab-docs/api-references/events/group-members-removed.md +++ b/playfab-docs/api-references/events/Groups/group-members-removed.md @@ -19,10 +19,10 @@ This event is triggered when a member is removed from an entity group |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |GroupName|String|The name of the group to which this event applies.| -|Members|[Member](data-types/member.md)|The list of entities that were removed from the group to which this event applies| +|Members|[Member](../data-types/member.md)|The list of entities that were removed from the group to which this event applies| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-created.md b/playfab-docs/api-references/events/Groups/group-role-created.md similarity index 83% rename from playfab-docs/api-references/events/group-role-created.md rename to playfab-docs/api-references/events/Groups/group-role-created.md index cfe9c5dfc..2b9433a8c 100644 --- a/playfab-docs/api-references/events/group-role-created.md +++ b/playfab-docs/api-references/events/Groups/group-role-created.md @@ -21,14 +21,14 @@ This event is triggered when a role is created for a group. |CreatorEntityId|String|The identifier for that the entity that created the role to which this event applies.| |CreatorEntityType|String|The type of entity that created the role to which this event applies.| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |GroupName|String|The name of the group to which this event applies.| |RoleId|String|The role ID of the role to which this event applies.| |RoleName|String|The display name of the role to which this event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-deleted.md b/playfab-docs/api-references/events/Groups/group-role-deleted.md similarity index 83% rename from playfab-docs/api-references/events/group-role-deleted.md rename to playfab-docs/api-references/events/Groups/group-role-deleted.md index 9733298b1..0c885d63a 100644 --- a/playfab-docs/api-references/events/group-role-deleted.md +++ b/playfab-docs/api-references/events/Groups/group-role-deleted.md @@ -21,14 +21,14 @@ This event is triggered when a role is deleted from a group. |DeleterEntityId|String|The identifier for the entity that deleted the role to which this event applies.| |DeleterEntityType|String|The type of entity that deleted the role to which this event applies.| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |GroupName|String|The name of the group to which this event applies.| |RoleId|String|The role ID of the role to which this event applies.| |RoleName|String|The display name of the role to which this event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-members-added.md b/playfab-docs/api-references/events/Groups/group-role-members-added.md similarity index 71% rename from playfab-docs/api-references/events/group-role-members-added.md rename to playfab-docs/api-references/events/Groups/group-role-members-added.md index 8d785c153..87251e7ad 100644 --- a/playfab-docs/api-references/events/group-role-members-added.md +++ b/playfab-docs/api-references/events/Groups/group-role-members-added.md @@ -19,15 +19,15 @@ This event is triggered when a list of entities are added to a role within a gro |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |GroupName|String|The name of the group to which this event applies.| -|Members|[Member](data-types/member.md)|The list of entities that were added to the group and role to which this event applies| +|Members|[Member](../data-types/member.md)|The list of entities that were added to the group and role to which this event applies| |RoleId|String|The role ID of the role to which this event applies.| |RoleName|String|The display name of the role to which this event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-members-removed.md b/playfab-docs/api-references/events/Groups/group-role-members-removed.md similarity index 71% rename from playfab-docs/api-references/events/group-role-members-removed.md rename to playfab-docs/api-references/events/Groups/group-role-members-removed.md index e38badb45..8712f082f 100644 --- a/playfab-docs/api-references/events/group-role-members-removed.md +++ b/playfab-docs/api-references/events/Groups/group-role-members-removed.md @@ -19,15 +19,15 @@ This event is triggered when a list of entities are removed from a role within a |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |GroupName|String|The name of the group to which this event applies.| -|Members|[Member](data-types/member.md)|The list of entities that were removed from the group to which this event applies| +|Members|[Member](../data-types/member.md)|The list of entities that were removed from the group to which this event applies| |RoleId|String|The role ID of the role to which this event applies.| |RoleName|String|The display name of the role to which this event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-role-updated.md b/playfab-docs/api-references/events/Groups/group-role-updated.md similarity index 69% rename from playfab-docs/api-references/events/group-role-updated.md rename to playfab-docs/api-references/events/Groups/group-role-updated.md index b3b4a9361..1a4f5d154 100644 --- a/playfab-docs/api-references/events/group-role-updated.md +++ b/playfab-docs/api-references/events/Groups/group-role-updated.md @@ -19,10 +19,10 @@ This event is triggered when a role is updated within a group. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |GroupName|String|The name of the group to which this event applies.| -|NewValues|[RolePropertyValues](data-types/rolepropertyvalues.md)|The new values of the role's changed properties| -|OldValues|[RolePropertyValues](data-types/rolepropertyvalues.md)|The previous values of the role's changed properties| +|NewValues|[RolePropertyValues](../data-types/rolepropertyvalues.md)|The new values of the role's changed properties| +|OldValues|[RolePropertyValues](../data-types/rolepropertyvalues.md)|The previous values of the role's changed properties| |RoleId|String|The role ID of the role to which this event applies.| |RoleName|String|The display name of the role to which this event applies.| |UpdaterEntityId|String|The identifier for the entity that updated the container to which this event applies.| @@ -30,6 +30,6 @@ This event is triggered when a role is updated within a group. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/group-updated.md b/playfab-docs/api-references/events/Groups/group-updated.md similarity index 64% rename from playfab-docs/api-references/events/group-updated.md rename to playfab-docs/api-references/events/Groups/group-updated.md index 2bc0ec7ca..fd55e7a9d 100644 --- a/playfab-docs/api-references/events/group-updated.md +++ b/playfab-docs/api-references/events/Groups/group-updated.md @@ -19,15 +19,15 @@ This event is triggered when an entity group is updated. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |GroupName|String|The name of the group to which this event applies.| -|NewValues|[GroupPropertyValues](data-types/grouppropertyvalues.md)|The new values of the group's changed properties| -|OldValues|[GroupPropertyValues](data-types/grouppropertyvalues.md)|The previous values of the group's changed properties| +|NewValues|[GroupPropertyValues](../data-types/grouppropertyvalues.md)|The new values of the group's changed properties| +|OldValues|[GroupPropertyValues](../data-types/grouppropertyvalues.md)|The previous values of the group's changed properties| |UpdaterEntityId|String|The identifier for the entity that updated the group to which this event applies.| |UpdaterEntityType|String|The type of entity that updated the group to which this event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Groups/members-added.md b/playfab-docs/api-references/events/Groups/members-added.md new file mode 100644 index 000000000..5309a7ffc --- /dev/null +++ b/playfab-docs/api-references/events/Groups/members-added.md @@ -0,0 +1,27 @@ +--- +title: members_added +author: joannaleecy +description: members_added event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# members_added + +This event is triggered when members are added to a group role. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Members|[EntityKey](../data-types/entitykey.md)[]|Entity keys of all members that were added to the role.| +|RoleId|String|Id of role members were added to.| +|RoleName|String|Name of role members were added to.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Groups/members-removed.md b/playfab-docs/api-references/events/Groups/members-removed.md new file mode 100644 index 000000000..a339bb0c1 --- /dev/null +++ b/playfab-docs/api-references/events/Groups/members-removed.md @@ -0,0 +1,27 @@ +--- +title: members_removed +author: joannaleecy +description: members_removed event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# members_removed + +This event is triggered when members are removed from a group role. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Members|[EntityKey](../data-types/entitykey.md)[]|Entity keys of all members that were removed from the role.| +|RoleId|String|Id of role members were removed from.| +|RoleName|String|Name of role members were removed from.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Groups/members-role-updated.md b/playfab-docs/api-references/events/Groups/members-role-updated.md new file mode 100644 index 000000000..6fcea50e2 --- /dev/null +++ b/playfab-docs/api-references/events/Groups/members-role-updated.md @@ -0,0 +1,28 @@ +--- +title: members_role_updated +author: joannaleecy +description: members_role_updated event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# members_role_updated + +This event is triggered when existing group members change from one role to another. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Members|[EntityKey](../data-types/entitykey.md)[]|Entity keys of all members that were updated with the role.| +|Operation|[OperationTypes](../data-types/operationtypes.md)|The operation that was performed.| +|RoleId|String|Id of the role.| +|RoleName|String|Name of the role.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Groups/player-updated-membership.md b/playfab-docs/api-references/events/Groups/player-updated-membership.md new file mode 100644 index 000000000..73d02b8a9 --- /dev/null +++ b/playfab-docs/api-references/events/Groups/player-updated-membership.md @@ -0,0 +1,31 @@ +--- +title: player_updated_membership +author: joannaleecy +description: player_updated_membership event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_updated_membership + +This event is triggered when a player's membership is updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|MembershipId|String|The unique identifier for the membership.| +|MembershipName|String|The name of the membership.| +|MembershipValue|[PlayerMemberships](../data-types/playermemberships.md)|The current membership value after the update.| +|PreviousMembershipValue|[PlayerMemberships](../data-types/playermemberships.md)|The previous membership value before the update.| +|SetViaOverride|Boolean|Whether the membership was set via an override.| +|TitleId|String|The ID of the title to which this player event applies.| +|UpdatedSubscription|[Subscriptions](../data-types/subscriptions.md)|The subscription that was updated.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/Groups/role-updated.md b/playfab-docs/api-references/events/Groups/role-updated.md new file mode 100644 index 000000000..8c7a2c12a --- /dev/null +++ b/playfab-docs/api-references/events/Groups/role-updated.md @@ -0,0 +1,28 @@ +--- +title: role_updated +author: joannaleecy +description: role_updated event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# role_updated + +This event is triggered when a group role is updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Operation|[OperationTypes](../data-types/operationtypes.md)|The operation that was performed.| +|PreviousRoleName|String|Previous name of the role.| +|RoleId|String|Id of the role to update.| +|RoleName|String|New name of the role.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Telemetry/apikey-activated.md b/playfab-docs/api-references/events/Telemetry/apikey-activated.md new file mode 100644 index 000000000..e617ae962 --- /dev/null +++ b/playfab-docs/api-references/events/Telemetry/apikey-activated.md @@ -0,0 +1,29 @@ +--- +title: apikey_activated +author: ronnyparedes +description: apikey_activated event. +ms.author: ronnyparedes +ms.date: 09/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# apikey_activated + +This event is triggered when an API key is activated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[APIKeyActivatedPayload](../data-types/apikeyactivatedpayload.md)|The payload of this event.| +|WriterEntity|[EntityKey](../data-types/entitykey.md)|The entity that wrote this event, included only if different from the entity specified on the event.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Telemetry/apikey-created.md b/playfab-docs/api-references/events/Telemetry/apikey-created.md new file mode 100644 index 000000000..17d6314c4 --- /dev/null +++ b/playfab-docs/api-references/events/Telemetry/apikey-created.md @@ -0,0 +1,29 @@ +--- +title: apikey_created +author: ronnyparedes +description: apikey_created event. +ms.author: ronnyparedes +ms.date: 09/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# apikey_created + +This event is triggered when an API key is created. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[APIKeyCreatedPayload](../data-types/apikeycreatedpayload.md)|The payload of this event.| +|WriterEntity|[EntityKey](../data-types/entitykey.md)|The entity that wrote this event, included only if different from the entity specified on the event.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Telemetry/apikey-deactivated.md b/playfab-docs/api-references/events/Telemetry/apikey-deactivated.md new file mode 100644 index 000000000..50e43ecbe --- /dev/null +++ b/playfab-docs/api-references/events/Telemetry/apikey-deactivated.md @@ -0,0 +1,29 @@ +--- +title: apikey_deactivated +author: ronnyparedes +description: apikey_deactivated event. +ms.author: ronnyparedes +ms.date: 09/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# apikey_deactivated + +This event is triggered when an API key is deactivated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[APIKeyDeactivatedPayload](../data-types/apikeydeactivatedpayload.md)|The payload of this event.| +|WriterEntity|[EntityKey](../data-types/entitykey.md)|The entity that wrote this event, included only if different from the entity specified on the event.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Telemetry/apikey-deleted.md b/playfab-docs/api-references/events/Telemetry/apikey-deleted.md new file mode 100644 index 000000000..100decc64 --- /dev/null +++ b/playfab-docs/api-references/events/Telemetry/apikey-deleted.md @@ -0,0 +1,29 @@ +--- +title: apikey_deleted +author: ronnyparedes +description: apikey_deleted event. +ms.author: ronnyparedes +ms.date: 09/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# apikey_deleted + +This event is triggered when an API key is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| +|OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| +|Payload|[APIKeyDeletedPayload](../data-types/apikeydeletedpayload.md)|The payload of this event.| +|WriterEntity|[EntityKey](../data-types/entitykey.md)|The entity that wrote this event, included only if different from the entity specified on the event.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/TitleCommunications/email-sent.md b/playfab-docs/api-references/events/TitleCommunications/email-sent.md new file mode 100644 index 000000000..712303ea9 --- /dev/null +++ b/playfab-docs/api-references/events/TitleCommunications/email-sent.md @@ -0,0 +1,29 @@ +--- +title: email_sent +author: ronnyparedes +description: email_sent event. +ms.author: ronnyparedes +ms.date: 09/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# email_sent + +This event is triggered when an email is sent to a player. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EmailName|String|The name of the player's contact email.| +|EmailTemplateId|String|The email template id.| +|EmailTemplateName|String|The friendly name of the Template.| +|ErrorMessage|String|The error that occurred if failed.| +|Succeeded|Boolean|Whether the email was sent successfully.| + +## Common Properties + +[!INCLUDE [playstream-events-common-properties-v2](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/player-registered-push-notifications.md b/playfab-docs/api-references/events/TitleCommunications/player-registered-push-notifications.md similarity index 74% rename from playfab-docs/api-references/events/player-registered-push-notifications.md rename to playfab-docs/api-references/events/TitleCommunications/player-registered-push-notifications.md index d59348226..22c06d0fb 100644 --- a/playfab-docs/api-references/events/player-registered-push-notifications.md +++ b/playfab-docs/api-references/events/TitleCommunications/player-registered-push-notifications.md @@ -19,9 +19,9 @@ This event is triggered when a player registers for push notifications. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |DeviceToken|String|Unique device token registered for push notifications.| -|Platform|[PushNotificationPlatform](data-types/pushnotificationplatform.md)|Platform on which the player is registering for push notifications.| +|Platform|[PushNotificationPlatform](../data-types/pushnotificationplatform.md)|Platform on which the player is registering for push notifications.| |TitleId|String|The ID of the title to which this player event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/TitleCommunications/push-notification-sent.md b/playfab-docs/api-references/events/TitleCommunications/push-notification-sent.md new file mode 100644 index 000000000..efd85760a --- /dev/null +++ b/playfab-docs/api-references/events/TitleCommunications/push-notification-sent.md @@ -0,0 +1,28 @@ +--- +title: push_notification_sent +author: joannaleecy +description: push_notification_sent event. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# push_notification_sent + +This event is triggered when a push notification is sent to a player. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ErrorMessage|String|The error that occurred if failed.| +|PushNotificationTemplateId|String|The push notification template id.| +|PushNotificationTemplateName|String|The friendly name of the push notification template.| +|Success|Boolean|Whether the push notification was sent successfully.| + +## Common Properties + +[!INCLUDE [playstream-events-common-properties-v2](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/sent-email.md b/playfab-docs/api-references/events/TitleCommunications/sent-email.md similarity index 81% rename from playfab-docs/api-references/events/sent-email.md rename to playfab-docs/api-references/events/TitleCommunications/sent-email.md index eb32b0daf..bb4734538 100644 --- a/playfab-docs/api-references/events/sent-email.md +++ b/playfab-docs/api-references/events/TitleCommunications/sent-email.md @@ -1,9 +1,9 @@ --- title: sent_email -author: joannaleecy +author: ronnyparedes description: sent_email event. -ms.author: jenelleb -ms.date: 02/19/2019 +ms.author: ronnyparedes +ms.date: 09/02/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events @@ -22,7 +22,7 @@ This event is triggered when an email is sent or fails to send to a player. |EmailName|String|The name of the player's contact email the email was sent to.| |EmailTemplateId|String|The email template id during a send email attempt.| |EmailTemplateName|String|The email template name during a send email attempt.| -|EmailTemplateType|[EmailTemplateType](data-types/emailtemplatetype.md)|The email template type during a send email attempt.| +|EmailTemplateType|[EmailTemplateType](../data-types/emailtemplatetype.md)|The email template type during a send email attempt.| |ErrorMessage|String|The error that occurred if an email failed to send.| |ErrorName|String|The name of the error that occurred if an email failed to send.| |Language|String|The language the email was sent in| @@ -33,4 +33,4 @@ This event is triggered when an email is sent or fails to send to a player. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/sent-push-notification.md b/playfab-docs/api-references/events/TitleCommunications/sent-push-notification.md similarity index 94% rename from playfab-docs/api-references/events/sent-push-notification.md rename to playfab-docs/api-references/events/TitleCommunications/sent-push-notification.md index dddd28587..6daa0839d 100644 --- a/playfab-docs/api-references/events/sent-push-notification.md +++ b/playfab-docs/api-references/events/TitleCommunications/sent-push-notification.md @@ -30,4 +30,4 @@ This event is triggered when a push notification is sent or fails to be sent to ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/data-types/apikeyactivatedpayload.md b/playfab-docs/api-references/events/data-types/apikeyactivatedpayload.md new file mode 100644 index 000000000..6d224a0ea --- /dev/null +++ b/playfab-docs/api-references/events/data-types/apikeyactivatedpayload.md @@ -0,0 +1,17 @@ +--- +author: WarrenAlpert +title: APIKeyActivatedPayload +description: Payload for when an entity API key is activated. +ms.author: waralper +ms.topic: reference +--- + +# APIKeyActivatedPayload + +Payload for when an entity API key is activated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|APIKeyId|String|Unique identifier for the entity API key.| diff --git a/playfab-docs/api-references/events/data-types/apikeycreatedpayload.md b/playfab-docs/api-references/events/data-types/apikeycreatedpayload.md new file mode 100644 index 000000000..35e670a2e --- /dev/null +++ b/playfab-docs/api-references/events/data-types/apikeycreatedpayload.md @@ -0,0 +1,18 @@ +--- +author: WarrenAlpert +title: APIKeyCreatedPayload +description: Payload for when an entity API key is created. +ms.author: waralper +ms.topic: reference +--- + +# APIKeyCreatedPayload + +Payload for when an entity API key is created. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|APIKeyId|String|Unique identifier for the entity API key.| +|Active|Boolean|Indicates whether the API key is active or not.| diff --git a/playfab-docs/api-references/events/data-types/apikeydeactivatedpayload.md b/playfab-docs/api-references/events/data-types/apikeydeactivatedpayload.md new file mode 100644 index 000000000..487df9ac9 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/apikeydeactivatedpayload.md @@ -0,0 +1,17 @@ +--- +author: WarrenAlpert +title: APIKeyDeactivatedPayload +description: Payload for when an entity API key is deactivated. +ms.author: waralper +ms.topic: reference +--- + +# APIKeyDeactivatedPayload + +Payload for when an entity API key is deactivated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|APIKeyId|String|Unique identifier for the entity API key.| diff --git a/playfab-docs/api-references/events/data-types/apikeydeletedpayload.md b/playfab-docs/api-references/events/data-types/apikeydeletedpayload.md new file mode 100644 index 000000000..5752b890c --- /dev/null +++ b/playfab-docs/api-references/events/data-types/apikeydeletedpayload.md @@ -0,0 +1,17 @@ +--- +author: WarrenAlpert +title: APIKeyDeletedPayload +description: Payload for when an entity API key is deleted. +ms.author: waralper +ms.topic: reference +--- + +# APIKeyDeletedPayload + +Payload for when an entity API key is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|APIKeyId|String|Unique identifier for the entity API key.| diff --git a/playfab-docs/api-references/events/data-types/artifact.md b/playfab-docs/api-references/events/data-types/artifact.md new file mode 100644 index 000000000..6c0f3fe05 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/artifact.md @@ -0,0 +1,23 @@ +--- +title: Artifact +author: ronnyparedes +description: Artifact data type. +ms.author: ronnyparedes +ms.date: 09/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# Artifact + +Provides details about an exported artifact (e.g Azure blob, Amazon S3 object, etc.) + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|NumberOfEvents|int64|The number of events in the artifact.| +|Path|String|The location in storage where the artifact was written to.| +|SizeInBytes|int64|The size of the artifact in bytes.| diff --git a/playfab-docs/api-references/events/data-types/eventexportcompletionstatus.md b/playfab-docs/api-references/events/data-types/eventexportcompletionstatus.md new file mode 100644 index 000000000..413ecfb9e --- /dev/null +++ b/playfab-docs/api-references/events/data-types/eventexportcompletionstatus.md @@ -0,0 +1,22 @@ +--- +title: EventExportCompletionStatus +author: joannaleecy +description: EventExportCompletionStatus data type. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# EventExportCompletionStatus + +The possible status upon completion of an event export execution. + +## Values + +|Name|Description| +| :--------------------|:----------------------| +|Failed|The export execution failed.| +|Succeeded|The export execution succeeded.| diff --git a/playfab-docs/api-references/events/data-types/executefunctionresult.md b/playfab-docs/api-references/events/data-types/executefunctionresult.md new file mode 100644 index 000000000..f095ec221 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/executefunctionresult.md @@ -0,0 +1,26 @@ +--- +title: ExecuteFunctionResult +author: joannaleecy +description: ExecuteFunctionResult data type. +ms.author: jenelleb +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ExecuteFunctionResult + +The result from executing a CloudScript Azure Function. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Error|[FunctionExecutionError](functionexecutionerror.md)|Error from the CloudScript Azure Function, if any.| +|ExecutionTimeMilliseconds|int|The amount of time the function took to execute in milliseconds.| +|FunctionName|String|The name of the function that executed.| +|FunctionResult|Object|The object returned from the function, if any.| +|FunctionResultSize|int|The size in bytes of the object returned from the function, if any.| +|FunctionResultTooLarge|Boolean|Flag indicating if the FunctionResult was too large and was subsequently dropped from this event.| diff --git a/playfab-docs/api-references/events/group-deleted.md b/playfab-docs/api-references/events/group-deleted.md deleted file mode 100644 index b37b002ac..000000000 --- a/playfab-docs/api-references/events/group-deleted.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: group_deleted -author: joannaleecy -description: group_deleted event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# group_deleted - -This event is triggered when an entity group is deleted. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|DeleterEntityId|String|The identifier for the entity that deleted the group to which this event applies.| -|DeleterEntityType|String|The type of entity that deleted the group to which this event applies.| -|EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|GroupName|String|The name of the group to which this event applies.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] - diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 83cc2b3fe..25b937ae7 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -69,56 +69,150 @@ Each event type has a set of properties that are included as part of event's dat - [cloudscript_executed](CloudScript/cloudscript-executed.md) This event is triggered when a CloudScript function is executed. -## General +## Extension -- [entity_created](entity-created.md) - This event is triggered when an entity is created. +- [title_aborted_task](Extension/title-aborted-task.md) + This event is triggered when a task instance is aborted. -- [entity_files_set](entity-files-set.md) - This event is triggered when files are attached to an entity. +- [title_completed_task](Extension/title-completed-task.md) + This event is triggered when a scheduled task has completed -- [entity_language_updated](entity-language-updated.md) - This event is triggered when the language associated with an entity is changed. +- [title_created_task](Extension/title-created-task.md) + This event is triggered when a task is created. -- [entity_logged_in](entity-logged-in.md) - This event is triggered when an entity has logged in. +- [title_deleted_task](Extension/title-deleted-task.md) + This event is triggered when a task is deleted. -- [entity_objects_set](entity-objects-set.md) - This event is triggered when objects are attached to an entity. +- [title_exceeded_limit](Extension/title-exceeded-limit.md) + This event is triggererd when a title exceeds a service limit and receives an error. -- [entity_virtual_currency_balances_changed](entity-virtual-currency-balances-changed.md) - This event is triggered when an entity's virtual currency balance changes. +- [title_limit_changed](Extension/title-limit-changed.md) + This event is triggered when a title changes a service limit. -- [group_created](group-created.md) - This event is triggered when an entity group is created. +- [title_started_task](Extension/title-started-task.md) + This event is triggered when a task is scheduled to run. -- [group_deleted](group-deleted.md) - This event is triggered when an entity group is deleted. +- [title_updated_task](Extension/title-updated-task.md) + This event is triggered when a task is updated. + +- [export_completed](Extension/export-completed.md) + This event is triggered when an export operation is completed. -- [group_members_added](group-members-added.md) +## Functions + +- [function_executed](Functions/function-executed.md) + This event is triggered when a function is executed. + +- [function_registered](Functions/function-registered.md) + This event is triggered when a function is registered. + +- [function_unregistered](Functions/function-unregistered.md) + This event is triggered when a function is unregistered. + +- [player_triggered_action_executed_function](Functions/player-triggered-action-executed-function.md) + This event is triggered when a function is run as the result of a PlayStream action. + +- [title_scheduled_function_executed](Functions/title-scheduled-function-executed.md) + This event is triggered when a function is run by a scheduled task. + +## Groups + +- [group_created](Groups/group-created.md) + This event is triggered when an entity group is created. + +- [group_members_added](Groups/group-members-added.md) This event is triggered when a member is added to an entity group. -- [group_members_removed](group-members-removed.md) +- [group_members_removed](Groups/group-members-removed.md) This event is triggered when a member is removed from an entity group. -- [group_role_created](group-role-created.md) +- [group_role_created](Groups/group-role-created.md) This event is triggered when a role is created for a group. -- [group_role_deleted](group-role-deleted.md) +- [group_role_deleted](Groups/group-role-deleted.md) This event is triggered when a role is deleted from a group. -- [group_role_members_added](group-role-members-added.md) +- [group_role_members_added](Groups/group-role-members-added.md) This event is triggered when a list of entities are added to a role within a group. -- [group_role_members_removed](group-role-members-removed.md) +- [group_role_members_removed](Groups/group-role-members-removed.md) This event is triggered when a list of entities are removed from a role within a group. -- [group_role_updated](group-role-updated.md) +- [group_role_updated](Groups/group-role-updated.md) This event is triggered when a role is updated within a group. -- [group_updated](group-updated.md) +- [group_updated](Groups/group-updated.md) This event is triggered when an entity group is updated. +- [members_added](Groups/members-added.md) + This event is triggered when members are added to a group. + +- [members_removed](Groups/members-removed.md) + This event is triggered when members are removed from a group. + +- [members_role_updated](Groups/members-role-updated.md) + This event is triggered when members' roles are updated in a group. + +- [player_updated_membership](Groups/player-updated-membership.md) + This event is triggered when a player's membership is updated. + +- [role_updated](Groups/role-updated.md) + This event is triggered when a role is updated. + +## Telemetry + +- [apikey_activated](Telemetry/apikey-activated.md) + This event is triggered when an API key is activated. + +- [apikey_created](Telemetry/apikey-created.md) + This event is triggered when an API key is created. + +- [apikey_deactivated](Telemetry/apikey-deactivated.md) + This event is triggered when an API key is deactivated. + +- [apikey_deleted](Telemetry/apikey-deleted.md) + This event is triggered when an API key is deleted. + +## TitleCommunications + +- [player_registered_push_notifications](TitleCommunications/player-registered-push-notifications.md) + This event is triggered when a player registers for push notifications. + +- [sent_email](TitleCommunications/sent-email.md) + This event is triggered when an email is sent or fails to send to a player. + +- [sent_push_notification](TitleCommunications/sent-push-notification.md) + This event is triggered when a push notification is sent or fails to be sent to a player. + +- [email_sent](TitleCommunications/email-sent.md) + This event is triggered when an email is sent. + +- [push_notification_sent](TitleCommunications/push-notification-sent.md) + This event is triggered when a push notification is sent. + +## General + +- [entity_created](entity-created.md) + This event is triggered when an entity is created. + +- [entity_files_set](entity-files-set.md) + This event is triggered when files are attached to an entity. + +- [entity_language_updated](entity-language-updated.md) + This event is triggered when the language associated with an entity is changed. + +- [entity_logged_in](entity-logged-in.md) + This event is triggered when an entity has logged in. + +- [entity_objects_set](entity-objects-set.md) + This event is triggered when objects are attached to an entity. + +- [entity_virtual_currency_balances_changed](entity-virtual-currency-balances-changed.md) + This event is triggered when an entity's virtual currency balance changes. + +- [group_deleted](group-deleted.md) + This event is triggered when an entity group is deleted. + - [matchmaking_match_found](matchmaking-match-found.md) This event is triggered when a group of tickets are matched together. @@ -387,9 +481,6 @@ Each event type has a set of properties that are included as part of event's dat - [player_redeemed_coupon](player-redeemed-coupon.md) This event is triggered when a player redeems a coupon. -- [player_registered_push_notifications](player-registered-push-notifications.md) - This event is triggered when a player registers for push notifications. - - [player_removed_title](player-removed-title.md) This event is triggered when a player account for a title is removed. Note: this event is triggered once per title rather than once per publisher. @@ -429,12 +520,6 @@ Each event type has a set of properties that are included as part of event's dat - [player_virtual_currency_balance_changed](player-virtual-currency-balance-changed.md) This event is triggered when a player's virtual currency balance changes. -- [sent_push_notification](sent-push-notification.md) - This event is triggered when a push notification is sent or fails to be sent to a player. - -- [sent_email](sent-email.md) - This event is triggered when an email is sent or fails to send to a player. - ## Session - [client_focus_change](client-focus-change.md) @@ -445,39 +530,21 @@ Each event type has a set of properties that are included as part of event's dat ## Title -- [title_aborted_task](title-aborted-task.md) - This event is triggered when a task instance is aborted. - - [title_catalog_updated](title-catalog-updated.md) This event is triggered when a catalog is changed. - [title_client_rate_limited_alert](title-client-rate-limited-alert.md) This event is triggered when a single IP address generates too many API calls to PlayFab and is throttled. -- [title_completed_task](title-completed-task.md) - This event is triggered when a scheduled task has completed - -- [title_created_task](title-created-task.md) - This event is triggered when a task is created. - - [title_deleted](title-deleted.md) This event is triggered when a game title is deleted. -- [title_deleted_task](title-deleted-task.md) - This event is triggered when a task is deleted. - -- [title_exceeded_limit](title-exceeded-limit.md) - This event is triggererd when a title exceeds a service limit and receives an error. - - [title_high_error_rate_alert](title-high-error-rate-alert.md) This event is triggered when a game title experiences a high rate of errors. - [title_initiated_player_password_reset](title-initiated-player-password-reset.md) This event is triggered when a title initiates the account recovery process for a player. -- [title_limit_changed](title-limit-changed.md) - This event is triggered when a title changes a service limit. - - [title_news_updated](title-news-updated.md) This event is triggered when a title news is created or updated. @@ -496,18 +563,12 @@ Each event type has a set of properties that are included as part of event's dat - [title_secret_key_changed](title-secret-key-changed.md) This event is triggered when a title adds or updates a Secret Key -- [title_started_task](title-started-task.md) - This event is triggered when a task is scheduled to run. - - [title_statistic_version_changed](title-statistic-version-changed.md) This event is triggered when the version of a statistic changes, causing its leaderboard to reset. - [title_store_updated](title-store-updated.md) This event is triggered when a store is changed. -- [title_updated_task](title-updated-task.md) - This event is triggered when a task is updated. - ## Statistics - [statistic_updated](statistic-updated.md) From 1d04ce99476b0cfd56031c5d6673fe7ed01836ad Mon Sep 17 00:00:00 2001 From: Jeffrey Shi Date: Wed, 11 Feb 2026 14:42:00 -0800 Subject: [PATCH 37/76] Introduction to the PlayFab SDK for Unreal Engine (v2) (#2806) Introduction to the PlayFab SDK for Unreal Engine (v2) --- playfab-docs/sdks/sdk-products.md | 76 ++++++ playfab-docs/sdks/toc.yml | 258 ++++++++++--------- playfab-docs/sdks/unified-unreal/overview.md | 79 ++++++ 3 files changed, 287 insertions(+), 126 deletions(-) create mode 100644 playfab-docs/sdks/sdk-products.md create mode 100644 playfab-docs/sdks/unified-unreal/overview.md diff --git a/playfab-docs/sdks/sdk-products.md b/playfab-docs/sdks/sdk-products.md new file mode 100644 index 000000000..c9aa0d3e8 --- /dev/null +++ b/playfab-docs/sdks/sdk-products.md @@ -0,0 +1,76 @@ +--- +title: PlayFab SDK Products +author: Jeffrey-Shi +description: Overview of PlayFab SDK product lines - v1 Standalone SDKs and v2 Unified SDK +ms.author: jeffshi +ms.date: 02/10/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playfab sdk, unified sdk, standalone sdk, sdk products +ms.localizationpriority: medium +--- + +# PlayFab SDK Products + +The **PlayFab Unified SDK (v2)** is the next generation of PlayFab SDKs, consolidating all PlayFab client libraries into a single, cohesive product. It provides a modern, streamlined development experience with unified authentication, automatic token management, and consistent APIs across all components. This is the primary focus of ongoing SDK development and will receive new features and platform support going forward. + +**For new projects**, we recommend the **PlayFab Unified SDK (v2)** if the currently supported platforms meet your requirements. **Existing projects** using v1 Standalone SDKs can [migrate to v2](unified-sdk/migrating-from-v1.md) to take advantage of the unified architecture. + +The **v1 Standalone SDKs** remain supported for now and provide broader platform coverage for projects that require platforms not yet supported in v2. + +> [!IMPORTANT] +> v1 and v2 SDKs cannot be used together in the same project. If you need a platform not yet supported in v2, use v1 for all components. + +## PlayFab Unified SDK (v2) + +The [PlayFab Unified SDK](unified-sdk/overview.md) provides a consistent, streamlined integration experience across all PlayFab components. + +### Key Benefits + +- **Single SDK**: One installation and update process for all PlayFab features +- **Unified Authentication**: Authenticate once and use the resulting entity handle across all components +- **Automatic Token Management**: Background token refresh prevents session expiration +- **Consistent Programming Model**: Standardized patterns for initialization, API calls, and error handling +- **Modern Development Practices**: Advanced memory management and thread control through XTaskQueue integration + +### Supported Platforms (v2) + +| Platform | Availability | +|----------|--------------| +| Windows (PC and Handheld) | Supported | +| Xbox (One, Series S/X, Cloud) | Supported | +| Steam Deck | Supported | +| PlayStation 5 | Coming soon | +| Nintendo Switch 2 | Coming soon | + +## PlayFab Standalone SDKs (v1) + +The [v1 Standalone SDKs](sdk-overview.md) consist of separate SDK packages for different PlayFab features. While still fully supported, they require managing multiple SDK installations and manual coordination between components. + +### SDK Components (v1) + +- **[PlayFab Services SDK](playfab-sdk-intro.md)**: LiveOps, economy, matchmaking, and data analytics +- **[PlayFab Party SDK](../multiplayer/networking/party-sdks.md)**: Networking and voice/text chat communication +- **[PlayFab Lobby and Matchmaking SDK](../multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md)**: Lobby and matchmaking features + +### Supported Platforms (v1) + +The v1 Standalone SDKs support a broader range of platforms: + +| Platform | Availability | +|----------|--------------| +| Windows (PC and Handheld) | Supported | +| Xbox (One, Series S/X, Cloud) | Supported | +| iOS | Supported | +| macOS | Supported | +| Android | Supported | +| Linux | Supported | +| PlayStation 4 | Supported (NDA required) | +| PlayStation 5 | Supported (NDA required) | +| Nintendo Switch | Supported (NDA required) | + +## See also + +- [PlayFab Unified SDK (v2)](unified-sdk/overview.md) +- [Standalone SDKs overview (v1)](sdk-overview.md) +- [Request access for SDKs and samples](request-access-for-sdks-samples.md) diff --git a/playfab-docs/sdks/toc.yml b/playfab-docs/sdks/toc.yml index 60e41850c..d49742c01 100644 --- a/playfab-docs/sdks/toc.yml +++ b/playfab-docs/sdks/toc.yml @@ -1,144 +1,150 @@ items: -- name: Overview - href: sdk-overview.md +- name: SDK Products + href: sdk-products.md - name: Request access href: request-access-for-sdks-samples.md -- name: PlayFab Unified SDK +- name: PlayFab Unified SDK (v2) href: unified-sdk/toc.yml -- name: Services SDKs +- name: PlayFab Unified SDK for Unreal Engine (v2) + href: unified-unreal/overview.md +- name: PlayFab Standalone SDKs (v1) items: - name: Overview - href: playfab-sdk-intro.md - - name: Release notes + href: sdk-overview.md + - name: Services SDKs (v1) items: - - name: C/C++ SDK release notes - href: ../release-notes/playfab-c/toc.yml - - name: Other SDK release notes - href: ../release-notes/toc.yml - - name: Languages - href: languages/index.yml - items: - - name: C/C++ - href: c/index.md + - name: Overview + href: playfab-sdk-intro.md + - name: Release notes + items: + - name: C/C++ SDK release notes + href: ../release-notes/playfab-c/toc.yml + - name: Other SDK release notes + href: ../release-notes/toc.yml + - name: Languages + href: languages/index.yml items: - - name: Quickstart - Win32 - href: c/quickstart-win32.md + - name: C/C++ + href: c/index.md + items: + - name: Quickstart - Win32 + href: c/quickstart-win32.md + - name: Quickstart - GDK + href: c/quickstart-gdk.md + - name: Quickstart - Android + href: c/quickstart-android.md + - name: Quickstart - iOS + href: c/quickstart-ios.md + - name: Quickstart - macOS + href: c/quickstart-macos.md + - name: Quickstart - Linux + href: c/quickstart-Linux.md + - name: Making Async Calls + href: c/async.md + - name: Managing Memory + href: c/memory.md + - name: Handling Token Expiration + href: c/relogin.md + - name: Debug Tracing + href: c/tracing.md + - name: Event Pipeline + href: c/event-pipeline/eventpipeline.md + items: + - name: Event Pipeline Tutorial + href: c/event-pipeline/eventpipeline-tutorial.md + - name: Initializing Servers + href: c/server.md + - name: Legacy C++ + href: playfab-cpp/index.md + items: - name: Quickstart - GDK - href: c/quickstart-gdk.md - - name: Quickstart - Android - href: c/quickstart-android.md - - name: Quickstart - iOS - href: c/quickstart-ios.md - - name: Quickstart - macOS - href: c/quickstart-macos.md + href: playfab-cpp/quickstart-gdk.md - name: Quickstart - Linux - href: c/quickstart-Linux.md - - name: Making Async Calls - href: c/async.md - - name: Managing Memory - href: c/memory.md - - name: Handling Token Expiration - href: c/relogin.md - - name: Debug Tracing - href: c/tracing.md - - name: Event Pipeline - href: c/event-pipeline/eventpipeline.md - items: - - name: Event Pipeline Tutorial - href: c/event-pipeline/eventpipeline-tutorial.md - - name: Initializing Servers - href: c/server.md - - name: Legacy C++ - href: playfab-cpp/index.md - items: - - name: Quickstart - GDK - href: playfab-cpp/quickstart-gdk.md - - name: Quickstart - Linux - href: playfab-cpp/quickstart-linux.md - - name: Quickstart - Windows - href: playfab-cpp/quickstart-windows.md - - name: C# - href: c-sharp/index.md - items: - - name: Quickstart - href: c-sharp/quickstart.md - - name: Java - href: java/index.md - items: - - name: Quickstart - href: java/quickstart.md - - name: JavaScript - href: javascript/index.md - items: - - name: Quickstart - href: javascript/quickstart.md - - name: Lua - href: lua/index.md - items: - - name: Quickstart - Corona - href: lua/quickstart-corona.md - - name: Quickstart - Defold - href: lua/quickstart-defold.md - - name: NodeJS - href: nodejs/index.md - items: - - name: Quickstart - href: nodejs/quickstart.md - - name: Objective-C - href: objective-c/index.md - items: - - name: Quickstart - href: objective-c/quickstart.md - - name: Python - href: python/index.md - items: - - name: Quickstart - href: python/quickstart.md - - name: Platforms - href: platforms/index.yml - items: - - name: Android - href: platforms/android.md - - name: iOS - href: platforms/ios.md - - name: macOS - href: platforms/macos.md - - name: Linux - href: platforms/linux.md - - name: Microsoft GDK - href: platforms/gdk.md - - name: Nintendo Switch - href: platforms/switch.md - - name: PS5 | PS4 - href: platforms/playstation.md - - name: Windows - href: platforms/windows.md - - name: Services and Tools - href: platforms/services.md - - name: Game engines - href: game-engines/index.yml - items: - - name: Cocos2d-x - href: cocos2d-x/index.md + href: playfab-cpp/quickstart-linux.md + - name: Quickstart - Windows + href: playfab-cpp/quickstart-windows.md + - name: C# + href: c-sharp/index.md + items: + - name: Quickstart + href: c-sharp/quickstart.md + - name: Java + href: java/index.md items: - name: Quickstart - href: cocos2d-x/quickstart.md - - name: Unity3D - href: unity3d/index.md + href: java/quickstart.md + - name: JavaScript + href: javascript/index.md items: - name: Quickstart - href: unity3d/quickstart.md - - name: Installing the PlayFab SDK for Unity - href: unity3d/installing-unity3d-sdk.md - - name: Unreal Engine - href: unreal/index.md + href: javascript/quickstart.md + - name: Lua + href: lua/index.md + items: + - name: Quickstart - Corona + href: lua/quickstart-corona.md + - name: Quickstart - Defold + href: lua/quickstart-defold.md + - name: Node.js + href: nodejs/index.md items: - name: Quickstart - href: unreal/quickstart.md -- name: Lobby and Matchmaking SDKs - href: ../multiplayer/lobby/lobby-matchmaking-sdks/toc.yml -- name: Party SDKs - href: ../multiplayer/networking/party-sdks/toc.yml + href: nodejs/quickstart.md + - name: Objective-C + href: objective-c/index.md + items: + - name: Quickstart + href: objective-c/quickstart.md + - name: Python + href: python/index.md + items: + - name: Quickstart + href: python/quickstart.md + - name: Platforms + href: platforms/index.yml + items: + - name: Android + href: platforms/android.md + - name: iOS + href: platforms/ios.md + - name: macOS + href: platforms/macos.md + - name: Linux + href: platforms/linux.md + - name: Microsoft GDK + href: platforms/gdk.md + - name: Nintendo Switch + href: platforms/switch.md + - name: PS5 | PS4 + href: platforms/playstation.md + - name: Windows + href: platforms/windows.md + - name: Services and Tools + href: platforms/services.md + - name: Game engines + href: game-engines/index.yml + items: + - name: Cocos2d-x + href: cocos2d-x/index.md + items: + - name: Quickstart + href: cocos2d-x/quickstart.md + - name: Unity3D + href: unity3d/index.md + items: + - name: Quickstart + href: unity3d/quickstart.md + - name: Installing the PlayFab SDK for Unity + href: unity3d/installing-unity3d-sdk.md + - name: Unreal Engine + href: unreal/index.md + items: + - name: Quickstart + href: unreal/quickstart.md + - name: Lobby and Matchmaking SDKs (v1) + href: ../multiplayer/lobby/lobby-matchmaking-sdks/toc.yml + - name: Party SDKs (v1) + href: ../multiplayer/networking/party-sdks/toc.yml - name: Multiplayer Server SDKs items: - name: Overview @@ -153,7 +159,7 @@ items: items: - name: Quickstart href: sdkgenerator/quickstart.md - - name: Postman + - name: Postman href: postman/index.md items: - name: Quickstart diff --git a/playfab-docs/sdks/unified-unreal/overview.md b/playfab-docs/sdks/unified-unreal/overview.md new file mode 100644 index 000000000..b029aaa6f --- /dev/null +++ b/playfab-docs/sdks/unified-unreal/overview.md @@ -0,0 +1,79 @@ +--- +title: PlayFab for Unreal Engine Overview +author: Jeffrey-Shi +description: Overview of PlayFab for Unreal Engine, the next-generation integration built on the PlayFab Unified SDK +ms.author: jeffshi +ms.date: 02/01/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, unreal engine, unified sdk, plugin, oss, onlinesubsystem, multiplayer, party +ms.localizationpriority: medium +--- + +# PlayFab for Unreal Engine (v2 Unified) + +PlayFab for Unreal Engine (v2 Unified) is the next-generation integration built on top of the [PlayFab Unified SDK](../unified-sdk/overview.md). It provides comprehensive integration with PlayFab's backend services for Unreal Engine game developers, bringing the modern development practices and unified architecture of the Unified SDK to the Unreal Engine ecosystem. + +## Overview + +PlayFab for Unreal Engine provides a unified integration experience, consolidating all PlayFab components into a single distribution. This distribution includes two main components: + +- **PlayFabUnreal**: Core plugin providing authentication, services, and game saves. Deliver PlayFab functionalities such as economy, leaderboards, player data, statistics, and more. +- **OnlineSubsystemPlayFab**: Online Subsystem (OSS) integration enabling Lobby, Matchmaking, Party networking, and Voice over Internet Protocol (VOIP). Includes cross-play, cross-platform communication, and accessibility features powered by Azure Cognitive Services such as real-time text chat translation and voice transcription. + +## Supported Platforms + +PlayFab for Unreal Engine is ready to power your games on these platforms today: + +- **Windows** (PC and Handheld) +- **Xbox** (One, Series S|X, Cloud) +- **Steam Deck** + +Support for additional platforms is in development. Check the [GitHub repository](https://github.com/PlayFab/PlayFabSDK_Unreal) for the latest platform availability updates. + +> [!IMPORTANT] +> We recommend PlayFab for Unreal Engine (v2 Unified) for all new projects. It offers a modern, unified architecture with an improved developer experience.
+ If your project requires a platform not yet supported in v2, use the [v1 PlayFab Unreal Plugin](../unreal/index.md) and [v1 OnlineSubsystem PlayFab](../../multiplayer/networking/party-unreal-engine-oss-overview.md) instead, as v1 and v2 cannot be used together in the same project. + +## Components + +### OnlineSubsystemPlayFab (OSS) + +The OnlineSubsystem PlayFab (OSS) provides full integration with Unreal Engine's Online Subsystem framework, enabling PlayFab's multiplayer and networking services through standard Unreal interfaces. This component includes: + +- **Lobby**: Create and manage game lobbies for multiplayer sessions using Unreal's session interfaces +- **Matchmaking**: Connect players based on skill, preferences, and other criteria +- **Party Data Communication**: Low-latency, cross-platform messaging for real-time multiplayer gameplay +- **Party Voice Chat**: Integrated voice communication with Azure Cognitive Services features like speech-to-text and translation + +The OSS integrates seamlessly with Unreal Engine's existing networking patterns, letting you use familiar Unreal APIs while leveraging PlayFab's scalable backend infrastructure. + +### PlayFabUnreal Plugin + +The PlayFabUnreal plugin provides core PlayFab functionality: + +- **PlayFab Core**: Authentication and event pipeline (telemetry) services that form the foundation for all PlayFab operations +- **PlayFab Services**: Game features including leaderboards, economy, player data, statistics, and catalog management +- **PlayFab Game Saves**: Cross-platform cloud saves for preserving player progress across devices and sessions + +## Getting Started + +For setup instructions and detailed documentation, visit the GitHub repository: + +**[PlayFab Unreal Engine Plugin on GitHub](https://github.com/PlayFab/PlayFabSDK_Unreal)** + +The repository includes: + +- Installation and configuration guides +- API reference documentation +- Sample projects and code examples +- Platform-specific setup instructions + +## Related Resources + +- [PlayFab Unified SDK Overview](../unified-sdk/overview.md) +- [v1 PlayFab Unreal Plugin](../unreal/index.md) +- [v1 OnlineSubsystem PlayFab](../../multiplayer/networking/party-unreal-engine-oss-overview.md) +- [PlayFab Game Saves](../../player-progression/game-saves/overview.md) +- [PlayFab Party](../../multiplayer/networking/party-sdks.md) +- [PlayFab Multiplayer](../../multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md) From 365f680d2d785392ed2d73574c381e69682f4232 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 15:21:08 -0800 Subject: [PATCH 38/76] Add manual testing capability to merge-main-to-live workflow (#2807) * Initial plan * Update merge-main-to-live workflow to match game-publishing-pr repo Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> * Fix output redirection to use append operator for GitHub Actions best practices Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> * Add logging for when no existing PR is found for better debugging Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: edigonzales-microsoft <235193640+edigonzales-microsoft@users.noreply.github.com> --- .github/workflows/merge-main-to-live.yml | 88 ++++++++++++++---------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/.github/workflows/merge-main-to-live.yml b/.github/workflows/merge-main-to-live.yml index c019e86b0..678ce98dc 100644 --- a/.github/workflows/merge-main-to-live.yml +++ b/.github/workflows/merge-main-to-live.yml @@ -5,12 +5,21 @@ on: # Run at 9:00 AM UTC every Tuesday - cron: '0 9 * * 2' workflow_dispatch: # Allow manual trigger for testing + inputs: + skip_date_check: + description: 'Skip the Tuesday date check for testing (select true to test immediately)' + required: false + default: 'false' + type: choice + options: + - 'false' + - 'true' jobs: merge: runs-on: ubuntu-latest permissions: - contents: read # Required for checking out code + contents: write # Required for creating pull requests via REST API pull-requests: write # Required for creating pull requests issues: write # Required for creating issues on failure @@ -21,66 +30,75 @@ jobs: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - - name: Check if today is 2nd or 4th Tuesday + - name: Check if it's 2nd or 4th Tuesday id: check_date run: | - # Get current day of month - DAY=$(date +%d) - # Get day of week (1=Monday, 2=Tuesday, ..., 7=Sunday) - DOW=$(date +%u) + # Check if we should skip the date check (for testing) + if [ "${{ github.event.inputs.skip_date_check }}" = "true" ]; then + echo "should_merge=true" >> $GITHUB_OUTPUT + echo "⚠️ TESTING MODE: Skipping date check as requested via workflow input" + exit 0 + fi - # Check if today is Tuesday (2) - if [ "$DOW" -eq 2 ]; then - # Calculate which week of the month we're in (1-5) - # Remove leading zero if present - DAY=$((10#$DAY)) - WEEK=$(( (DAY - 1) / 7 + 1 )) - - # Check if it's the 2nd or 4th Tuesday - if [ "$WEEK" -eq 2 ] || [ "$WEEK" -eq 4 ]; then - echo "is_target_tuesday=true" >> $GITHUB_OUTPUT - echo "This is the 2nd or 4th Tuesday of the month" - else - echo "is_target_tuesday=false" >> $GITHUB_OUTPUT - echo "This is not the 2nd or 4th Tuesday" - fi + # Get the current day of the month + day=$(date +%d) + # Remove leading zero if present + day=$((10#$day)) + + # Calculate which week of the month we're in (1-5) + week=$(( (day - 1) / 7 + 1 )) + + # Get the current day of week (1=Monday, 2=Tuesday, ..., 7=Sunday) + dow=$(date +%u) + + echo "Day of month: $day" + echo "Week of month: $week" + echo "Day of week: $dow" + + # Check if today is Tuesday (dow=2) and it's the 2nd or 4th week + if [ "$dow" = "2" ] && ([ "$week" = "2" ] || [ "$week" = "4" ]); then + echo "should_merge=true" >> $GITHUB_OUTPUT + echo "This is the 2nd or 4th Tuesday of the month. Proceeding with merge." else - echo "is_target_tuesday=false" >> $GITHUB_OUTPUT - echo "Today is not Tuesday" + echo "should_merge=false" >> $GITHUB_OUTPUT + echo "Not the 2nd or 4th Tuesday. Skipping merge." fi - name: Check for existing PR - if: steps.check_date.outputs.is_target_tuesday == 'true' + if: steps.check_date.outputs.should_merge == 'true' id: check_pr uses: actions/github-script@v7 with: script: | + // Check for open PR from main to live (lowercase for testing) const { data: pulls } = await github.rest.pulls.list({ owner: context.repo.owner, repo: context.repo.repo, state: 'open', - head: `${context.repo.owner}:Main`, - base: 'Live' + head: `${context.repo.owner}:main`, + base: 'live' }); if (pulls.length > 0) { core.setOutput('pr_exists', 'true'); core.setOutput('pr_number', pulls[0].number); core.setOutput('pr_url', pulls[0].html_url); + console.log(`Existing PR found: ${pulls[0].html_url}`); } else { core.setOutput('pr_exists', 'false'); + console.log('No existing PR found. Will create a new one.'); } - name: Create Pull Request - if: steps.check_date.outputs.is_target_tuesday == 'true' && steps.check_pr.outputs.pr_exists == 'false' + if: steps.check_date.outputs.should_merge == 'true' && steps.check_pr.outputs.pr_exists == 'false' id: create_pr uses: actions/github-script@v7 with: script: | const date = new Date().toISOString().split('T')[0]; - const title = `Scheduled Merge: Main to Live on ${date}`; + const title = `Scheduled Merge: main to live on ${date}`; const body = [ - 'This is an automated pull request to merge Main into Live branch.', + 'This is an automated pull request to merge main branch into live branch.', '', `**Scheduled merge date:** ${date}`, `**Schedule:** This PR is created on the 2nd and 4th Tuesday of each month.`, @@ -92,7 +110,7 @@ jobs: '- Code owners should approve this PR', '- Merge when ready', '', - 'If there are conflicts, they will need to be resolved manually.', + 'If there are conflicts, they can be resolved in the GitHub UI or locally.', '', '---', '*This PR was automatically created by the scheduled merge workflow.*' @@ -104,8 +122,8 @@ jobs: repo: context.repo.repo, title: title, body: body, - head: 'Main', - base: 'Live' + head: 'main', + base: 'live' }); core.setOutput('pr_number', pr.number); @@ -117,7 +135,7 @@ jobs: } - name: Comment on existing PR - if: steps.check_date.outputs.is_target_tuesday == 'true' && steps.check_pr.outputs.pr_exists == 'true' + if: steps.check_date.outputs.should_merge == 'true' && steps.check_pr.outputs.pr_exists == 'true' uses: actions/github-script@v7 env: PR_NUMBER: ${{ steps.check_pr.outputs.pr_number }} @@ -143,7 +161,7 @@ jobs: console.log(`Comment added to existing PR #${prNumber}`); - name: Create Issue on Failure - if: failure() && steps.check_date.outputs.is_target_tuesday == 'true' + if: failure() && steps.check_date.outputs.should_merge == 'true' uses: actions/github-script@v7 with: script: | @@ -162,5 +180,5 @@ jobs: repo: context.repo.repo, title: title, body: body, - labels: ['workflow-failure', 'automated'] + labels: ['merge-conflict', 'automated'] }); From 08875a4f656e88415536468afbb4562915fe192b Mon Sep 17 00:00:00 2001 From: edigonzales-microsoft Date: Fri, 13 Feb 2026 09:47:00 -0800 Subject: [PATCH 39/76] Update CODEOWNERS to remove users (#2811) Removed specific users from CODEOWNERS for playfab-docs. --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f13af9242..0ba70ebab 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,4 +5,4 @@ # The '*' pattern is global owners. -/playfab-docs/ @MicrosoftDocs/xbox-learning-resources @williacj @thomasgu +/playfab-docs/ @MicrosoftDocs/xbox-learning-resources From 50195c8827033ec06de8e1a3e7d5033c8e5b3823 Mon Sep 17 00:00:00 2001 From: ronnyparedesc <113482725+ronnyparedesc@users.noreply.github.com> Date: Fri, 13 Feb 2026 10:06:30 -0800 Subject: [PATCH 40/76] Playstream event documentation update for Player Identity, Player Profile, Title Data, Developer Identity (#2809) * Player Identity * Player Profile * Title data * Dev identity * Update author" --- .../{ => DeveloperIdentity}/studio-created.md | 2 +- .../studio-user-added.md | 4 +- .../studio-user-invited.md | 4 +- .../studio-user-removed.md | 4 +- .../auth-token-validated.md | 2 +- .../{ => PlayerIdentity}/character-created.md | 2 +- .../{ => PlayerIdentity}/entity-created.md | 4 +- .../events/PlayerIdentity/entity-deleted.md | 23 ++ .../{ => PlayerIdentity}/entity-logged-in.md | 4 +- .../PlayerIdentity/logged-in-to-title.md | 25 ++ .../player-added-title.md | 4 +- .../PlayerIdentity/player-authenticated.md | 27 ++ .../{ => PlayerIdentity}/player-banned.md | 2 +- .../player-changed-avatar.md | 2 +- .../player-completed-password-reset.md | 4 +- .../{ => PlayerIdentity}/player-created.md | 2 +- .../player-custom-properties-changed.md | 40 +++ .../player-data-exported.md | 2 +- .../player-device-info.md | 2 +- .../player-displayname-changed.md | 2 +- .../player-identity-link-added.md | 27 ++ .../player-identity-link-removed.md | 27 ++ .../player-linked-account.md | 4 +- .../{ => PlayerIdentity}/player-logged-in.md | 6 +- .../player-password-reset-link-sent.md | 4 +- .../player-removed-title.md | 2 +- .../player-reported-as-abusive.md | 2 +- .../{ => PlayerIdentity}/player-tag-added.md | 2 +- .../player-tag-removed.md | 2 +- .../player-unlinked-account.md | 4 +- .../player-updated-contact-email.md | 2 +- .../player-updated-login-email.md | 27 ++ .../player-verified-contact-email.md | 2 +- .../title-deleted-master-player.md | 2 +- .../title-initiated-player-password-reset.md | 2 +- .../title-profile-view-constraints-changed.md | 2 +- .../PlayerProfile/access-policy-updated.md | 27 ++ .../PlayerProfile/avatar-url-updated.md | 25 ++ .../PlayerProfile/contact-email-updated.md | 27 ++ .../{ => PlayerProfile}/entity-files-set.md | 6 +- .../entity-language-updated.md | 4 +- .../{ => PlayerProfile}/entity-objects-set.md | 6 +- .../events/PlayerProfile/files-changed.md | 25 ++ .../events/PlayerProfile/language-updated.md | 25 ++ .../events/PlayerProfile/objects-updated.md | 25 ++ .../events/TitleData/title-activated.md | 19 ++ .../TitleData/title-data-override-deleted.md | 26 ++ .../events/TitleData/title-data-updated.md | 27 ++ .../events/TitleData/title-deactivated.md | 19 ++ .../{ => TitleData}/title-news-updated.md | 4 +- .../title-secret-key-changed.md | 2 +- .../events/data-types/contactemaildetails.md | 22 ++ .../events/data-types/filedetails.md | 29 ++ .../events/data-types/objectdetails.md | 23 ++ .../playercustompropertieschangeddetails.md | 23 ++ .../events/data-types/titledatatype.md | 22 ++ playfab-docs/api-references/events/index.md | 258 +++++++++++------- 57 files changed, 768 insertions(+), 154 deletions(-) rename playfab-docs/api-references/events/{ => DeveloperIdentity}/studio-created.md (88%) rename playfab-docs/api-references/events/{ => DeveloperIdentity}/studio-user-added.md (81%) rename playfab-docs/api-references/events/{ => DeveloperIdentity}/studio-user-invited.md (83%) rename playfab-docs/api-references/events/{ => DeveloperIdentity}/studio-user-removed.md (79%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/auth-token-validated.md (89%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/character-created.md (88%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/entity-created.md (72%) create mode 100644 playfab-docs/api-references/events/PlayerIdentity/entity-deleted.md rename playfab-docs/api-references/events/{ => PlayerIdentity}/entity-logged-in.md (73%) create mode 100644 playfab-docs/api-references/events/PlayerIdentity/logged-in-to-title.md rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-added-title.md (79%) create mode 100644 playfab-docs/api-references/events/PlayerIdentity/player-authenticated.md rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-banned.md (90%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-changed-avatar.md (88%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-completed-password-reset.md (85%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-created.md (90%) create mode 100644 playfab-docs/api-references/events/PlayerIdentity/player-custom-properties-changed.md rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-data-exported.md (90%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-device-info.md (87%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-displayname-changed.md (89%) create mode 100644 playfab-docs/api-references/events/PlayerIdentity/player-identity-link-added.md create mode 100644 playfab-docs/api-references/events/PlayerIdentity/player-identity-link-removed.md rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-linked-account.md (78%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-logged-in.md (64%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-password-reset-link-sent.md (81%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-removed-title.md (88%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-reported-as-abusive.md (89%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-tag-added.md (88%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-tag-removed.md (88%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-unlinked-account.md (75%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-updated-contact-email.md (91%) create mode 100644 playfab-docs/api-references/events/PlayerIdentity/player-updated-login-email.md rename playfab-docs/api-references/events/{ => PlayerIdentity}/player-verified-contact-email.md (90%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/title-deleted-master-player.md (89%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/title-initiated-player-password-reset.md (91%) rename playfab-docs/api-references/events/{ => PlayerIdentity}/title-profile-view-constraints-changed.md (91%) create mode 100644 playfab-docs/api-references/events/PlayerProfile/access-policy-updated.md create mode 100644 playfab-docs/api-references/events/PlayerProfile/avatar-url-updated.md create mode 100644 playfab-docs/api-references/events/PlayerProfile/contact-email-updated.md rename playfab-docs/api-references/events/{ => PlayerProfile}/entity-files-set.md (66%) rename playfab-docs/api-references/events/{ => PlayerProfile}/entity-language-updated.md (76%) rename playfab-docs/api-references/events/{ => PlayerProfile}/entity-objects-set.md (66%) create mode 100644 playfab-docs/api-references/events/PlayerProfile/files-changed.md create mode 100644 playfab-docs/api-references/events/PlayerProfile/language-updated.md create mode 100644 playfab-docs/api-references/events/PlayerProfile/objects-updated.md create mode 100644 playfab-docs/api-references/events/TitleData/title-activated.md create mode 100644 playfab-docs/api-references/events/TitleData/title-data-override-deleted.md create mode 100644 playfab-docs/api-references/events/TitleData/title-data-updated.md create mode 100644 playfab-docs/api-references/events/TitleData/title-deactivated.md rename playfab-docs/api-references/events/{ => TitleData}/title-news-updated.md (77%) rename playfab-docs/api-references/events/{ => TitleData}/title-secret-key-changed.md (91%) create mode 100644 playfab-docs/api-references/events/data-types/contactemaildetails.md create mode 100644 playfab-docs/api-references/events/data-types/filedetails.md create mode 100644 playfab-docs/api-references/events/data-types/objectdetails.md create mode 100644 playfab-docs/api-references/events/data-types/playercustompropertieschangeddetails.md create mode 100644 playfab-docs/api-references/events/data-types/titledatatype.md diff --git a/playfab-docs/api-references/events/studio-created.md b/playfab-docs/api-references/events/DeveloperIdentity/studio-created.md similarity index 88% rename from playfab-docs/api-references/events/studio-created.md rename to playfab-docs/api-references/events/DeveloperIdentity/studio-created.md index 23121f972..96542a1f8 100644 --- a/playfab-docs/api-references/events/studio-created.md +++ b/playfab-docs/api-references/events/DeveloperIdentity/studio-created.md @@ -24,4 +24,4 @@ This event is triggered when a studio is created. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/studio-user-added.md b/playfab-docs/api-references/events/DeveloperIdentity/studio-user-added.md similarity index 81% rename from playfab-docs/api-references/events/studio-user-added.md rename to playfab-docs/api-references/events/DeveloperIdentity/studio-user-added.md index a8847b0fa..167183312 100644 --- a/playfab-docs/api-references/events/studio-user-added.md +++ b/playfab-docs/api-references/events/DeveloperIdentity/studio-user-added.md @@ -17,7 +17,7 @@ ms.localizationpriority: medium |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |AuthenticationId|String|Authentication provider's ID for this user| -|AuthenticationProvider|[AuthenticationProvider](data-types/authenticationprovider.md)|Authentication provider for the user| +|AuthenticationProvider|[AuthenticationProvider](../data-types/authenticationprovider.md)|Authentication provider for the user| |AuthenticationProviderId|String|Authentication provider entity id, if needed by the provider| |Email|String|User's email| |InvitationId|String|Id of the invitation record if user needed to register| @@ -27,4 +27,4 @@ ms.localizationpriority: medium ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/studio-user-invited.md b/playfab-docs/api-references/events/DeveloperIdentity/studio-user-invited.md similarity index 83% rename from playfab-docs/api-references/events/studio-user-invited.md rename to playfab-docs/api-references/events/DeveloperIdentity/studio-user-invited.md index f6052de64..8b7d90640 100644 --- a/playfab-docs/api-references/events/studio-user-invited.md +++ b/playfab-docs/api-references/events/DeveloperIdentity/studio-user-invited.md @@ -18,7 +18,7 @@ This event is triggererd when a user is invited to a studio. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|AuthenticationProvider|[AuthenticationProvider](data-types/authenticationprovider.md)|Authentication provider type required for user to register with| +|AuthenticationProvider|[AuthenticationProvider](../data-types/authenticationprovider.md)|Authentication provider type required for user to register with| |AuthenticationProviderId|String|Authentication provider entity id, if needed by the provider.| |Email|String|Email the invitation was sent to| |InvitationExpires|DateTime|Expiration of the invitation| @@ -30,4 +30,4 @@ This event is triggererd when a user is invited to a studio. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/studio-user-removed.md b/playfab-docs/api-references/events/DeveloperIdentity/studio-user-removed.md similarity index 79% rename from playfab-docs/api-references/events/studio-user-removed.md rename to playfab-docs/api-references/events/DeveloperIdentity/studio-user-removed.md index fa0853d5c..0acee9dc5 100644 --- a/playfab-docs/api-references/events/studio-user-removed.md +++ b/playfab-docs/api-references/events/DeveloperIdentity/studio-user-removed.md @@ -19,7 +19,7 @@ This event is triggered when a user is removed from a studio. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |AuthenticationId|String|Authentication provider's ID for this user| -|AuthenticationProvider|[AuthenticationProvider](data-types/authenticationprovider.md)|Authentication provider for the user| +|AuthenticationProvider|[AuthenticationProvider](../data-types/authenticationprovider.md)|Authentication provider for the user| |AuthenticationProviderId|String|Authentication provider entity id, if needed by the provider| |PlayFabId|String|PlayFab ID for this user| |StudioPermissions|[]|Array of studio permissions that the user had| @@ -28,4 +28,4 @@ This event is triggered when a user is removed from a studio. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/auth-token-validated.md b/playfab-docs/api-references/events/PlayerIdentity/auth-token-validated.md similarity index 89% rename from playfab-docs/api-references/events/auth-token-validated.md rename to playfab-docs/api-references/events/PlayerIdentity/auth-token-validated.md index ef68c556a..ea069fd13 100644 --- a/playfab-docs/api-references/events/auth-token-validated.md +++ b/playfab-docs/api-references/events/PlayerIdentity/auth-token-validated.md @@ -24,4 +24,4 @@ This event is triggered when an email confirmation link is clicked. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-created.md b/playfab-docs/api-references/events/PlayerIdentity/character-created.md similarity index 88% rename from playfab-docs/api-references/events/character-created.md rename to playfab-docs/api-references/events/PlayerIdentity/character-created.md index 04fdef752..f505551b9 100644 --- a/playfab-docs/api-references/events/character-created.md +++ b/playfab-docs/api-references/events/PlayerIdentity/character-created.md @@ -25,4 +25,4 @@ This event is triggered when a character is created for the first time. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/entity-created.md b/playfab-docs/api-references/events/PlayerIdentity/entity-created.md similarity index 72% rename from playfab-docs/api-references/events/entity-created.md rename to playfab-docs/api-references/events/PlayerIdentity/entity-created.md index 9a0a3e057..9676df678 100644 --- a/playfab-docs/api-references/events/entity-created.md +++ b/playfab-docs/api-references/events/PlayerIdentity/entity-created.md @@ -19,8 +19,8 @@ This event is triggered when an entity is created. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/PlayerIdentity/entity-deleted.md b/playfab-docs/api-references/events/PlayerIdentity/entity-deleted.md new file mode 100644 index 000000000..04fa4b9dd --- /dev/null +++ b/playfab-docs/api-references/events/PlayerIdentity/entity-deleted.md @@ -0,0 +1,23 @@ +--- +title: entity_deleted +author: ronnyparedes +description: entity_deleted event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# entity_deleted + +This event is triggered upon deletion of an entity. + +## Properties + +This event has no additional properties beyond the common properties. The entity context is provided in the common properties. + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/entity-logged-in.md b/playfab-docs/api-references/events/PlayerIdentity/entity-logged-in.md similarity index 73% rename from playfab-docs/api-references/events/entity-logged-in.md rename to playfab-docs/api-references/events/PlayerIdentity/entity-logged-in.md index ffee1d260..8f1b80b56 100644 --- a/playfab-docs/api-references/events/entity-logged-in.md +++ b/playfab-docs/api-references/events/PlayerIdentity/entity-logged-in.md @@ -19,10 +19,10 @@ This event is triggered when an entity has logged in. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/PlayerIdentity/logged-in-to-title.md b/playfab-docs/api-references/events/PlayerIdentity/logged-in-to-title.md new file mode 100644 index 000000000..0c5a894da --- /dev/null +++ b/playfab-docs/api-references/events/PlayerIdentity/logged-in-to-title.md @@ -0,0 +1,25 @@ +--- +title: logged_in_to_title +author: ronnyparedes +description: logged_in_to_title event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# logged_in_to_title + +This event is triggered when a master_player_account entity logs in to a title to obtain a title_player_account entity token. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityTokenId|String|Unique identifier for the generated title_player_account entity token.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/player-added-title.md b/playfab-docs/api-references/events/PlayerIdentity/player-added-title.md similarity index 79% rename from playfab-docs/api-references/events/player-added-title.md rename to playfab-docs/api-references/events/PlayerIdentity/player-added-title.md index 6b97edbe1..68357d292 100644 --- a/playfab-docs/api-references/events/player-added-title.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-added-title.md @@ -19,10 +19,10 @@ This event is triggered when a player creates a new account for a title. Note: t |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |DisplayName|String|Player's display name when they added this title.| -|Platform|[LoginIdentityProvider](data-types/loginidentityprovider.md)|Authentication method used to register player's account.| +|Platform|[LoginIdentityProvider](../data-types/loginidentityprovider.md)|Authentication method used to register player's account.| |PlatformUserId|String|Unique ID for the player's account associated with the Origination authentication method.| |TitleId|String|The ID of the title to which this player event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-authenticated.md b/playfab-docs/api-references/events/PlayerIdentity/player-authenticated.md new file mode 100644 index 000000000..ed6505531 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerIdentity/player-authenticated.md @@ -0,0 +1,27 @@ +--- +title: player_authenticated +author: ronnyparedes +description: player_authenticated event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_authenticated + +This event is triggered when a player account (master_player_account entity) is authenticated using a player identity from a player identity provider. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EntityTokenId|String|Unique identifier for the generated master_player_account entity token for authenticating subsequent API calls.| +|IdentityProvider|String|Name of the player identity provider used to authenticate the player identity.| +|IdentityProviderIssuedId|String|Unique ID of the player identity within the player identity provider.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/player-banned.md b/playfab-docs/api-references/events/PlayerIdentity/player-banned.md similarity index 90% rename from playfab-docs/api-references/events/player-banned.md rename to playfab-docs/api-references/events/PlayerIdentity/player-banned.md index 45a0583a0..96f646051 100644 --- a/playfab-docs/api-references/events/player-banned.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-banned.md @@ -26,4 +26,4 @@ This event is triggered when a player is banned. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-changed-avatar.md b/playfab-docs/api-references/events/PlayerIdentity/player-changed-avatar.md similarity index 88% rename from playfab-docs/api-references/events/player-changed-avatar.md rename to playfab-docs/api-references/events/PlayerIdentity/player-changed-avatar.md index 3cea56e7a..cba786a9d 100644 --- a/playfab-docs/api-references/events/player-changed-avatar.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-changed-avatar.md @@ -24,4 +24,4 @@ This event is triggered when a player's avatar URL is changed. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-completed-password-reset.md b/playfab-docs/api-references/events/PlayerIdentity/player-completed-password-reset.md similarity index 85% rename from playfab-docs/api-references/events/player-completed-password-reset.md rename to playfab-docs/api-references/events/PlayerIdentity/player-completed-password-reset.md index 1146cdfbf..3e54c89b6 100644 --- a/playfab-docs/api-references/events/player-completed-password-reset.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-completed-password-reset.md @@ -20,7 +20,7 @@ This event is triggered when a player completes the password reset process by vi | :--------------------|:-------------------|:----------------------| |CompletedFromIPAddress|String|IP address from which the password reset process was completed.| |CompletionTimestamp|DateTime|When the password reset process was completed.| -|InitiatedBy|[PasswordResetInitiationSource](data-types/passwordresetinitiationsource.md)|Source that initiated the password reset process.| +|InitiatedBy|[PasswordResetInitiationSource](../data-types/passwordresetinitiationsource.md)|Source that initiated the password reset process.| |InitiatedFromIPAddress|String|IP address from which the password reset process was initiated.| |InitiationTimestamp|DateTime|When the password reset process was initiated.| |LinkExpiration|DateTime|Expiration time for the password reset link.| @@ -30,4 +30,4 @@ This event is triggered when a player completes the password reset process by vi ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-created.md b/playfab-docs/api-references/events/PlayerIdentity/player-created.md similarity index 90% rename from playfab-docs/api-references/events/player-created.md rename to playfab-docs/api-references/events/PlayerIdentity/player-created.md index 286dbb347..0b20f2e33 100644 --- a/playfab-docs/api-references/events/player-created.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-created.md @@ -24,4 +24,4 @@ This event is triggered when a player account is created for the first time. Not ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-custom-properties-changed.md b/playfab-docs/api-references/events/PlayerIdentity/player-custom-properties-changed.md new file mode 100644 index 000000000..f5a26d1a8 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerIdentity/player-custom-properties-changed.md @@ -0,0 +1,40 @@ +--- +title: player_custom_properties_changed +author: ronnyparedes +description: player_custom_properties_changed event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_custom_properties_changed + +This event is triggered when a player's custom properties are altered. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ChangeDetails|[PlayerCustomPropertiesChangedDetails](../data-types/playercustompropertieschangeddetails.md)[]|Set of changes being applied to the player's custom properties.| +|TitleId|String|The ID of the title to which this player event applies.| + +## Common Properties + +All PlayStream events are formatted as JSON objects and share the following common properties: + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CustomTags|Object|Key-Value pair storage. Any provider of this event schema is allowed to send additional values in this property.| +|EntityId|String|The identifier for the entity (title, player, etc) to which this event applies.| +|EntityType|String|The type of entity (player, title, etc.) to which this event applies. If PlayFab is meant to take action on this entity, then the EntityType must be either 'player', 'character', or 'title'. It is required that any entity type that PlayFab does not currently parse should be prepended with a namespace (like 'com.mygame.guild') as PlayFab may begin to parse root entities at any time.| +|EventId|String|PlayFab-assigned unique identifier for this event.| +|EventName|String|The name of this event.| +|EventNamespace|String|The assigned namespacing for this event. For example: 'com.myprogram.ads'| +|History|[PlayStreamEventHistory](../data-types/playstreameventhistory.md)|The history of events associated with this event. This is set in cases where an event has generated children events via a trigger action.| +|Reserved|object|Reserved exclusively for PlayFab internal use.| +|Source|String|The name of the source of this PlayStream event; will be PlayFab if the event originated from us.| +|SourceType|[SourceType](../data-types/sourcetype.md)|The type of source of this event (PlayFab partner, other backend, or from the PlayFab API).| +|Timestamp|DateTime|The time (in UTC) associated with this event.| diff --git a/playfab-docs/api-references/events/player-data-exported.md b/playfab-docs/api-references/events/PlayerIdentity/player-data-exported.md similarity index 90% rename from playfab-docs/api-references/events/player-data-exported.md rename to playfab-docs/api-references/events/PlayerIdentity/player-data-exported.md index 377a7733f..56f9944b3 100644 --- a/playfab-docs/api-references/events/player-data-exported.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-data-exported.md @@ -25,4 +25,4 @@ This event is triggered when a player's data is exported. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-device-info.md b/playfab-docs/api-references/events/PlayerIdentity/player-device-info.md similarity index 87% rename from playfab-docs/api-references/events/player-device-info.md rename to playfab-docs/api-references/events/PlayerIdentity/player-device-info.md index 509c7ddb3..32462d47f 100644 --- a/playfab-docs/api-references/events/player-device-info.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-device-info.md @@ -23,4 +23,4 @@ This event is triggered once after the player logs in based on the settings for ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-displayname-changed.md b/playfab-docs/api-references/events/PlayerIdentity/player-displayname-changed.md similarity index 89% rename from playfab-docs/api-references/events/player-displayname-changed.md rename to playfab-docs/api-references/events/PlayerIdentity/player-displayname-changed.md index 3074abf6f..7a0f2d82d 100644 --- a/playfab-docs/api-references/events/player-displayname-changed.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-displayname-changed.md @@ -24,4 +24,4 @@ This event is triggered when a player's display name is changed. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-added.md b/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-added.md new file mode 100644 index 000000000..fe585cf32 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-added.md @@ -0,0 +1,27 @@ +--- +title: player_identity_link_added +author: ronnyparedes +description: player_identity_link_added event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_identity_link_added + +This event is triggered when a player identity from a player identity provider is linked to a master_player_account entity. After linking, the player identity may be used to authenticate the master_player_account. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|IdentityLinkId|String|Unique identifier of the added link between the player identity and master_player_account.| +|IdentityProvider|String|Name of the player identity provider in which the linked identity exists.| +|IdentityProviderIssuedId|String|Unique identifier of the linked player identity, as assigned by the player identity provider.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-removed.md b/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-removed.md new file mode 100644 index 000000000..fcd1951c2 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-removed.md @@ -0,0 +1,27 @@ +--- +title: player_identity_link_removed +author: ronnyparedes +description: player_identity_link_removed event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_identity_link_removed + +This event is triggered when a player identity from a player identity provider is unlinked from a master_player_account entity. After unlinking, the player identity may no longer be used to authenticate the master_player_account. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|IdentityLinkId|String|Unique identifier of the removed link between the player identity and master_player_account.| +|IdentityProvider|String|Name of the player identity provider in which the unlinked identity exists.| +|IdentityProviderIssuedId|String|Unique identifier of the unlinked player identity, as assigned by the player identity provider.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/player-linked-account.md b/playfab-docs/api-references/events/PlayerIdentity/player-linked-account.md similarity index 78% rename from playfab-docs/api-references/events/player-linked-account.md rename to playfab-docs/api-references/events/PlayerIdentity/player-linked-account.md index 1e0070203..7c71f0eef 100644 --- a/playfab-docs/api-references/events/player-linked-account.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-linked-account.md @@ -19,11 +19,11 @@ This event is triggered when a new authentication method is linked to a player's |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |Email|String|Player's email linked with the given provider| -|Origination|[LoginIdentityProvider](data-types/loginidentityprovider.md)|Authentication method being linked to a player's account.| +|Origination|[LoginIdentityProvider](../data-types/loginidentityprovider.md)|Authentication method being linked to a player's account.| |OriginationUserId|String|Player's identity under authentication method being linked to player's account.| |TitleId|String|The ID of the title to which this player event applies.| |Username|String|Player's username linked with the given provider| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-logged-in.md b/playfab-docs/api-references/events/PlayerIdentity/player-logged-in.md similarity index 64% rename from playfab-docs/api-references/events/player-logged-in.md rename to playfab-docs/api-references/events/PlayerIdentity/player-logged-in.md index 96776ea58..a2cdf2bd7 100644 --- a/playfab-docs/api-references/events/player-logged-in.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-logged-in.md @@ -18,12 +18,12 @@ This event is triggered when a player logs in. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|Location|[EventLocation](data-types/eventlocation.md)|Player's geographic location, if known. Location is estimated from factors such as IP address and is not always available or accurate.| -|Platform|[LoginIdentityProvider](data-types/loginidentityprovider.md)|Authentication method used to login the player.| +|Location|[EventLocation](../data-types/eventlocation.md)|Player's geographic location, if known. Location is estimated from factors such as IP address and is not always available or accurate.| +|Platform|[LoginIdentityProvider](../data-types/loginidentityprovider.md)|Authentication method used to login the player.| |PlatformUserId|String|Player's identity under the authentication method used to login the player.| |PlatformUserName|String|The display name that's set in the identity provider that the player is authenticated with.| |TitleId|String|The ID of the title to which this player event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-password-reset-link-sent.md b/playfab-docs/api-references/events/PlayerIdentity/player-password-reset-link-sent.md similarity index 81% rename from playfab-docs/api-references/events/player-password-reset-link-sent.md rename to playfab-docs/api-references/events/PlayerIdentity/player-password-reset-link-sent.md index 4b5c9907a..2173727a5 100644 --- a/playfab-docs/api-references/events/player-password-reset-link-sent.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-password-reset-link-sent.md @@ -18,7 +18,7 @@ This event is triggered when a player is sent a link to reset their password. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|InitiatedBy|[PasswordResetInitiationSource](data-types/passwordresetinitiationsource.md)|Source that initiated the password reset process.| +|InitiatedBy|[PasswordResetInitiationSource](../data-types/passwordresetinitiationsource.md)|Source that initiated the password reset process.| |InitiatedFromIPAddress|String|IP address from which the password reset process was initiated.| |LinkExpiration|DateTime|Expiration time for the password reset link.| |PasswordResetId|String|Unique identifier for the password reset link. This cannot be used to complete the reset.| @@ -27,4 +27,4 @@ This event is triggered when a player is sent a link to reset their password. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-removed-title.md b/playfab-docs/api-references/events/PlayerIdentity/player-removed-title.md similarity index 88% rename from playfab-docs/api-references/events/player-removed-title.md rename to playfab-docs/api-references/events/PlayerIdentity/player-removed-title.md index 4624f3fbb..e90f7563a 100644 --- a/playfab-docs/api-references/events/player-removed-title.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-removed-title.md @@ -22,4 +22,4 @@ This event is triggered when a player account for a title is removed. Note: this ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-reported-as-abusive.md b/playfab-docs/api-references/events/PlayerIdentity/player-reported-as-abusive.md similarity index 89% rename from playfab-docs/api-references/events/player-reported-as-abusive.md rename to playfab-docs/api-references/events/PlayerIdentity/player-reported-as-abusive.md index 6adc548a6..311513ea1 100644 --- a/playfab-docs/api-references/events/player-reported-as-abusive.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-reported-as-abusive.md @@ -24,4 +24,4 @@ This event is triggered when a player is reported by another player as abusive. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-tag-added.md b/playfab-docs/api-references/events/PlayerIdentity/player-tag-added.md similarity index 88% rename from playfab-docs/api-references/events/player-tag-added.md rename to playfab-docs/api-references/events/PlayerIdentity/player-tag-added.md index 353a81dbc..f9b6db274 100644 --- a/playfab-docs/api-references/events/player-tag-added.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-tag-added.md @@ -24,4 +24,4 @@ This event is triggered when a tag is added to a player profile. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-tag-removed.md b/playfab-docs/api-references/events/PlayerIdentity/player-tag-removed.md similarity index 88% rename from playfab-docs/api-references/events/player-tag-removed.md rename to playfab-docs/api-references/events/PlayerIdentity/player-tag-removed.md index fadc9c1ff..c63c7b304 100644 --- a/playfab-docs/api-references/events/player-tag-removed.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-tag-removed.md @@ -24,4 +24,4 @@ This event is triggered when a tag is removed from a player profile. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-unlinked-account.md b/playfab-docs/api-references/events/PlayerIdentity/player-unlinked-account.md similarity index 75% rename from playfab-docs/api-references/events/player-unlinked-account.md rename to playfab-docs/api-references/events/PlayerIdentity/player-unlinked-account.md index 5bcb86db8..c6e6846b7 100644 --- a/playfab-docs/api-references/events/player-unlinked-account.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-unlinked-account.md @@ -18,10 +18,10 @@ This event is triggered when an authentication method is unlinked from a player' |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|Origination|[LoginIdentityProvider](data-types/loginidentityprovider.md)|Authentication method being unlinked from a player's account.| +|Origination|[LoginIdentityProvider](../data-types/loginidentityprovider.md)|Authentication method being unlinked from a player's account.| |OriginationUserId|String|Player's identity under authentication method being unlinked from player's account.| |TitleId|String|The ID of the title to which this player event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-updated-contact-email.md b/playfab-docs/api-references/events/PlayerIdentity/player-updated-contact-email.md similarity index 91% rename from playfab-docs/api-references/events/player-updated-contact-email.md rename to playfab-docs/api-references/events/PlayerIdentity/player-updated-contact-email.md index fdfa83a46..282168e4e 100644 --- a/playfab-docs/api-references/events/player-updated-contact-email.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-updated-contact-email.md @@ -25,4 +25,4 @@ This event is triggered when a player updates a contact email on their profile. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-updated-login-email.md b/playfab-docs/api-references/events/PlayerIdentity/player-updated-login-email.md new file mode 100644 index 000000000..d077c6207 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerIdentity/player-updated-login-email.md @@ -0,0 +1,27 @@ +--- +title: player_updated_login_email +author: ronnyparedes +description: player_updated_login_email event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_updated_login_email + +This event is triggered when a player's login email is updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|NewEmailAddress|String|The login email updated in the player's profile.| +|PreviousEmailAddress|String|The previous login email updated in the player's profile.| +|TitleId|String|The ID of the title to which this player event applies.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/player-verified-contact-email.md b/playfab-docs/api-references/events/PlayerIdentity/player-verified-contact-email.md similarity index 90% rename from playfab-docs/api-references/events/player-verified-contact-email.md rename to playfab-docs/api-references/events/PlayerIdentity/player-verified-contact-email.md index 14489ac0e..810fb54b5 100644 --- a/playfab-docs/api-references/events/player-verified-contact-email.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-verified-contact-email.md @@ -24,4 +24,4 @@ This event is triggered when a contact email is verified for a player. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-deleted-master-player.md b/playfab-docs/api-references/events/PlayerIdentity/title-deleted-master-player.md similarity index 89% rename from playfab-docs/api-references/events/title-deleted-master-player.md rename to playfab-docs/api-references/events/PlayerIdentity/title-deleted-master-player.md index 10e686b6a..49f879ad3 100644 --- a/playfab-docs/api-references/events/title-deleted-master-player.md +++ b/playfab-docs/api-references/events/PlayerIdentity/title-deleted-master-player.md @@ -24,4 +24,4 @@ This event is triggered when a GDPR delete is finished. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-initiated-player-password-reset.md b/playfab-docs/api-references/events/PlayerIdentity/title-initiated-player-password-reset.md similarity index 91% rename from playfab-docs/api-references/events/title-initiated-player-password-reset.md rename to playfab-docs/api-references/events/PlayerIdentity/title-initiated-player-password-reset.md index 40bf72bd1..e454a687f 100644 --- a/playfab-docs/api-references/events/title-initiated-player-password-reset.md +++ b/playfab-docs/api-references/events/PlayerIdentity/title-initiated-player-password-reset.md @@ -26,4 +26,4 @@ This event is triggered when a title initiates the account recovery process for ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-profile-view-constraints-changed.md b/playfab-docs/api-references/events/PlayerIdentity/title-profile-view-constraints-changed.md similarity index 91% rename from playfab-docs/api-references/events/title-profile-view-constraints-changed.md rename to playfab-docs/api-references/events/PlayerIdentity/title-profile-view-constraints-changed.md index f3dff05ec..2a719433e 100644 --- a/playfab-docs/api-references/events/title-profile-view-constraints-changed.md +++ b/playfab-docs/api-references/events/PlayerIdentity/title-profile-view-constraints-changed.md @@ -26,4 +26,4 @@ This event is triggered when a profile view constraint is changed for the title. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/PlayerProfile/access-policy-updated.md b/playfab-docs/api-references/events/PlayerProfile/access-policy-updated.md new file mode 100644 index 000000000..806fed0d4 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerProfile/access-policy-updated.md @@ -0,0 +1,27 @@ +--- +title: access_policy_updated +author: ronnyparedes +description: access_policy_updated event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# access_policy_updated + +This event is triggered when a profile access policy has been updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|AccessPolicy|String[]|The new access policy statements.| +|Operation|[OperationTypes](../data-types/operationtypes.md)|The type of operation that was performed on the access policy.| +|PreviousAccessPolicy|String[]|The previous access policy statements.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/PlayerProfile/avatar-url-updated.md b/playfab-docs/api-references/events/PlayerProfile/avatar-url-updated.md new file mode 100644 index 000000000..02c20c164 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerProfile/avatar-url-updated.md @@ -0,0 +1,25 @@ +--- +title: avatar_url_updated +author: ronnyparedes +description: avatar_url_updated event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# avatar_url_updated + +This event is triggered when the avatar URL of a profile has been updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|AvatarUrl|String|The new avatar URL for the profile.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/PlayerProfile/contact-email-updated.md b/playfab-docs/api-references/events/PlayerProfile/contact-email-updated.md new file mode 100644 index 000000000..544807b2e --- /dev/null +++ b/playfab-docs/api-references/events/PlayerProfile/contact-email-updated.md @@ -0,0 +1,27 @@ +--- +title: contact_email_updated +author: ronnyparedes +description: contact_email_updated event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# contact_email_updated + +This event is triggered when the contact email addresses of a profile have been updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ContactEmails|[ContactEmailDetails](../data-types/contactemaildetails.md)[]|The new contact email addresses for the profile.| +|Operation|[OperationTypes](../data-types/operationtypes.md)|The type of operation that was performed on the contact emails.| +|PreviousContactEmails|[ContactEmailDetails](../data-types/contactemaildetails.md)[]|The previous contact email addresses for the profile.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/entity-files-set.md b/playfab-docs/api-references/events/PlayerProfile/entity-files-set.md similarity index 66% rename from playfab-docs/api-references/events/entity-files-set.md rename to playfab-docs/api-references/events/PlayerProfile/entity-files-set.md index 0301e68e0..ac39c47ab 100644 --- a/playfab-docs/api-references/events/entity-files-set.md +++ b/playfab-docs/api-references/events/PlayerProfile/entity-files-set.md @@ -19,9 +19,9 @@ This event is triggered when files are attached to an entity. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Files|[FileSet](data-types/fileset.md)|The files that were updated.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Files|[FileSet](../data-types/fileset.md)|The files that were updated.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/entity-language-updated.md b/playfab-docs/api-references/events/PlayerProfile/entity-language-updated.md similarity index 76% rename from playfab-docs/api-references/events/entity-language-updated.md rename to playfab-docs/api-references/events/PlayerProfile/entity-language-updated.md index 0b985283b..8d58a181c 100644 --- a/playfab-docs/api-references/events/entity-language-updated.md +++ b/playfab-docs/api-references/events/PlayerProfile/entity-language-updated.md @@ -19,10 +19,10 @@ This event is triggered when the language associated with an entity is changed. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |Language|String|Language that was updated| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/entity-objects-set.md b/playfab-docs/api-references/events/PlayerProfile/entity-objects-set.md similarity index 66% rename from playfab-docs/api-references/events/entity-objects-set.md rename to playfab-docs/api-references/events/PlayerProfile/entity-objects-set.md index d40e4b3a9..6eb65e038 100644 --- a/playfab-docs/api-references/events/entity-objects-set.md +++ b/playfab-docs/api-references/events/PlayerProfile/entity-objects-set.md @@ -19,9 +19,9 @@ This event is triggered when objects are attached to an entity. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Objects|[ObjectSet](data-types/objectset.md)|Objects that were updated| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Objects|[ObjectSet](../data-types/objectset.md)|Objects that were updated| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] \ No newline at end of file +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/PlayerProfile/files-changed.md b/playfab-docs/api-references/events/PlayerProfile/files-changed.md new file mode 100644 index 000000000..95464cf14 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerProfile/files-changed.md @@ -0,0 +1,25 @@ +--- +title: files_changed +author: ronnyparedes +description: files_changed event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# files_changed + +This event summarizes the changes to files that are attached to an entity. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Files|[FileDetails](../data-types/filedetails.md)[]|The files that were updated.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/PlayerProfile/language-updated.md b/playfab-docs/api-references/events/PlayerProfile/language-updated.md new file mode 100644 index 000000000..6fedefc46 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerProfile/language-updated.md @@ -0,0 +1,25 @@ +--- +title: language_updated +author: ronnyparedes +description: language_updated event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# language_updated + +This event is triggered when the language of a profile has been updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Language|String|The new language for the profile.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/PlayerProfile/objects-updated.md b/playfab-docs/api-references/events/PlayerProfile/objects-updated.md new file mode 100644 index 000000000..2df40b4a9 --- /dev/null +++ b/playfab-docs/api-references/events/PlayerProfile/objects-updated.md @@ -0,0 +1,25 @@ +--- +title: objects_updated +author: ronnyparedes +description: objects_updated event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# objects_updated + +This event summarizes the changes to objects that are attached to an entity. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Objects|[ObjectDetails](../data-types/objectdetails.md)[]|The objects that were updated.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/TitleData/title-activated.md b/playfab-docs/api-references/events/TitleData/title-activated.md new file mode 100644 index 000000000..7c2ae0e3d --- /dev/null +++ b/playfab-docs/api-references/events/TitleData/title-activated.md @@ -0,0 +1,19 @@ +--- +title: title_activated +author: ronnyparedes +description: title_activated event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# title_activated + +This event is triggered when a title is activated. + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/TitleData/title-data-override-deleted.md b/playfab-docs/api-references/events/TitleData/title-data-override-deleted.md new file mode 100644 index 000000000..b2e80bb9f --- /dev/null +++ b/playfab-docs/api-references/events/TitleData/title-data-override-deleted.md @@ -0,0 +1,26 @@ +--- +title: title_data_override_deleted +author: ronnyparedes +description: title_data_override_deleted event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# title_data_override_deleted + +This event is triggered when a title data override is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|OverrideLabel|String|The override label that was deleted.| +|TitleDataType|[TitleDataType](../data-types/titledatatype.md)|The type of title data.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/TitleData/title-data-updated.md b/playfab-docs/api-references/events/TitleData/title-data-updated.md new file mode 100644 index 000000000..2e638de98 --- /dev/null +++ b/playfab-docs/api-references/events/TitleData/title-data-updated.md @@ -0,0 +1,27 @@ +--- +title: title_data_updated +author: ronnyparedes +description: title_data_updated event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# title_data_updated + +This event is triggered when title data is updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Keys|String[]|The keys that were updated.| +|OverrideLabel|String|The override label. Empty if primary title data.| +|TitleDataType|[TitleDataType](../data-types/titledatatype.md)|The type of title data.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/TitleData/title-deactivated.md b/playfab-docs/api-references/events/TitleData/title-deactivated.md new file mode 100644 index 000000000..bfc97b320 --- /dev/null +++ b/playfab-docs/api-references/events/TitleData/title-deactivated.md @@ -0,0 +1,19 @@ +--- +title: title_deactivated +author: ronnyparedes +description: title_deactivated event. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# title_deactivated + +This event is triggered when a title is deactivated. + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/title-news-updated.md b/playfab-docs/api-references/events/TitleData/title-news-updated.md similarity index 77% rename from playfab-docs/api-references/events/title-news-updated.md rename to playfab-docs/api-references/events/TitleData/title-news-updated.md index 71882bc84..501eeec5d 100644 --- a/playfab-docs/api-references/events/title-news-updated.md +++ b/playfab-docs/api-references/events/TitleData/title-news-updated.md @@ -21,8 +21,8 @@ This event is triggered when a title news is created or updated. |DateCreated|DateTime|When the title news was initially created.| |NewsId|String|Id of the news that is new or updated.| |NewsTitle|String|The current title of the news that is new or updated.| -|Status|[NewsStatus](data-types/newsstatus.md)|The current status of the news that is new or updated.| +|Status|[NewsStatus](../data-types/newsstatus.md)|The current status of the news that is new or updated.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-secret-key-changed.md b/playfab-docs/api-references/events/TitleData/title-secret-key-changed.md similarity index 91% rename from playfab-docs/api-references/events/title-secret-key-changed.md rename to playfab-docs/api-references/events/TitleData/title-secret-key-changed.md index 77e5001ad..61065b9df 100644 --- a/playfab-docs/api-references/events/title-secret-key-changed.md +++ b/playfab-docs/api-references/events/TitleData/title-secret-key-changed.md @@ -28,4 +28,4 @@ This event is triggered when a title adds or updates a Secret Key ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/data-types/contactemaildetails.md b/playfab-docs/api-references/events/data-types/contactemaildetails.md new file mode 100644 index 000000000..2b74037f3 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/contactemaildetails.md @@ -0,0 +1,22 @@ +--- +title: ContactEmailDetails +author: ronnyparedes +description: ContactEmailDetails data type. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ContactEmailDetails + +Details about a contact email address associated with an entity profile. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|EmailAddress|String|The email address.| +|EmailType|String|The type of contact email (e.g., primary, backup).| diff --git a/playfab-docs/api-references/events/data-types/filedetails.md b/playfab-docs/api-references/events/data-types/filedetails.md new file mode 100644 index 000000000..95139b6a2 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/filedetails.md @@ -0,0 +1,29 @@ +--- +title: FileDetails +author: ronnyparedes +description: FileDetails data type. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# FileDetails + +Details about a file attached to an entity. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ByteCount|int32|The current size of the file in bytes.| +|Checksum|String|The current checksum of the file.| +|FileName|String|The name of the file.| +|Operation|[OperationTypes](operationtypes.md)|The type of operation that was performed on the file.| +|PreviousByteCount|int32|The previous size of the file in bytes.| +|PreviousChecksum|String|The previous checksum of the file.| +|PreviousStoragePath|String|The previous storage path of the file.| +|StoragePath|String|The current storage path of the file.| +|StorageSystem|[ProfileFileStorage](profilefilestorage.md)|The storage system where the file is stored.| diff --git a/playfab-docs/api-references/events/data-types/objectdetails.md b/playfab-docs/api-references/events/data-types/objectdetails.md new file mode 100644 index 000000000..8f3a7ea14 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/objectdetails.md @@ -0,0 +1,23 @@ +--- +title: ObjectDetails +author: ronnyparedes +description: ObjectDetails data type. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ObjectDetails + +Details about an object attached to an entity. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|DataObject|object|The data object content.| +|Name|String|The name of the object.| +|Operation|[OperationTypes](operationtypes.md)|The type of operation that was performed on the object.| diff --git a/playfab-docs/api-references/events/data-types/playercustompropertieschangeddetails.md b/playfab-docs/api-references/events/data-types/playercustompropertieschangeddetails.md new file mode 100644 index 000000000..12fa66db5 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/playercustompropertieschangeddetails.md @@ -0,0 +1,23 @@ +--- +title: PlayerCustomPropertiesChangedDetails +author: ronnyparedes +description: PlayerCustomPropertiesChangedDetails data type. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# PlayerCustomPropertiesChangedDetails + +Details about a custom property change. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Name|String|The name of the custom property that was changed.| +|OperationType|[PlayerCustomPropertiesChangedOperationTypes](playercustompropertieschangedoperationtypes.md)|The operation that was performed.| +|Value|object|The last set value of the custom property.| diff --git a/playfab-docs/api-references/events/data-types/titledatatype.md b/playfab-docs/api-references/events/data-types/titledatatype.md new file mode 100644 index 000000000..5f95ce9d9 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/titledatatype.md @@ -0,0 +1,22 @@ +--- +title: TitleDataType +author: ronnyparedes +description: TitleDataType data type. +ms.author: ronnyparedes +ms.date: 12/02/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# TitleDataType + +Specifies the type of title data. + +## Values + +|Name|Value|Description| +| :--------------------|:-------------------|:----------------------| +|TitleData|0|Public title data accessible to all clients.| +|TitleInternalData|1|Internal title data only accessible server-side.| diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 25b937ae7..a84b4869d 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -69,6 +69,20 @@ Each event type has a set of properties that are included as part of event's dat - [cloudscript_executed](CloudScript/cloudscript-executed.md) This event is triggered when a CloudScript function is executed. +## DeveloperIdentity + +- [studio_created](DeveloperIdentity/studio-created.md) + This event is triggered when a studio is created. + +- [studio_user_added](DeveloperIdentity/studio-user-added.md) + This event is triggered when a user accepts a studio invitation. + +- [studio_user_invited](DeveloperIdentity/studio-user-invited.md) + This event is triggered when a user is invited to a studio. + +- [studio_user_removed](DeveloperIdentity/studio-user-removed.md) + This event is triggered when a user is removed from a studio. + ## Extension - [title_aborted_task](Extension/title-aborted-task.md) @@ -192,21 +206,6 @@ Each event type has a set of properties that are included as part of event's dat ## General -- [entity_created](entity-created.md) - This event is triggered when an entity is created. - -- [entity_files_set](entity-files-set.md) - This event is triggered when files are attached to an entity. - -- [entity_language_updated](entity-language-updated.md) - This event is triggered when the language associated with an entity is changed. - -- [entity_logged_in](entity-logged-in.md) - This event is triggered when an entity has logged in. - -- [entity_objects_set](entity-objects-set.md) - This event is triggered when objects are attached to an entity. - - [entity_virtual_currency_balances_changed](entity-virtual-currency-balances-changed.md) This event is triggered when an entity's virtual currency balance changes. @@ -225,18 +224,6 @@ Each event type has a set of properties that are included as part of event's dat - [matchmaking_user_ticket_invite](matchmaking-user-ticket-invite.md) This event is triggered when a ticket with an invited user is created. The event will be sent to the invited user. -- [studio_created](studio-created.md) - This event is triggered when a studio is created. - -- [studio_user_added](studio-user-added.md) - This event is triggered when a user accepts a studio invitation. - -- [studio_user_invited](studio-user-invited.md) - This event is triggered when a user is invited to a studio. - -- [studio_user_removed](studio-user-removed.md) - This event is triggered when a user is removed from a studio. - - [tenancy_connector_onboard](tenancy-connector-onboard.md) This event is triggered when a tenancy connector is onboarded. @@ -351,8 +338,6 @@ Each event type has a set of properties that are included as part of event's dat - [character_consumed_item](character-consumed-item.md) This event is triggered when a character consumes an item from their inventory. -- [character_created](character-created.md) - This event is triggered when a character is created for the first time. - [character_inventory_item_added](character-inventory-item-added.md) This event is triggered when an item is granted to a character. @@ -412,60 +397,18 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a player connects to a Photon Cloud application and authenticates with PlayFab using Photon custom authentication. ## Player - -- [auth_token_validated](auth-token-validated.md) - This event is triggered when an email confirmation link is clicked. - -- [title_deleted_master_player](title-deleted-master-player.md) - This event is triggered when a GDPR delete is finished. - - [player_action_executed](player-action-executed.md) This event is triggered when an action linked to a segmentation change or event rule executes on a player. - [player_ad_campaign_attribution](player-ad-campaign-attribution.md) This event is triggered by an attribution tracking Add-on when a player is matched to a paid acquisition campaign. -- [player_added_title](player-added-title.md) - This event is triggered when a player creates a new account for a title. Note: this event is triggered once per title rather than once per publisher. - - - -- [player_banned](player-banned.md) - This event is triggered when a player is banned. - -- [player_changed_avatar](player-changed-avatar.md) - This event is triggered when a player's avatar URL is changed. - -- [player_completed_password_reset](player-completed-password-reset.md) - This event is triggered when a player completes the password reset process by visiting the link URL that was sent to them and choosing a new password. - - [player_consumed_item](player-consumed-item.md) This event is triggered when a player consumes an item from their inventory. -- [player_created](player-created.md) - This event is triggered when a player account is created for the first time. Note: this event is only triggered once per publisher, not once per title. - -- [player_data_exported](player-data-exported.md) - This event is triggered when a player's data is exported. - -- [player_device_info](player-device-info.md) - This event is triggered once after the player logs in based on the settings for your title. - -- [player_displayname_changed](player-displayname-changed.md) - This event is triggered when a player's display name is changed. - - [player_inventory_item_added](player-inventory-item-added.md) This event is triggered when an item is granted to a player. -- [player_linked_account](player-linked-account.md) - This event is triggered when a new authentication method is linked to a player's account. - -- [player_logged_in](player-logged-in.md) - This event is triggered when a player logs in. - -- [player_password_reset_link_sent](player-password-reset-link-sent.md) - This event is triggered when a player is sent a link to reset their password. - - [player_paid_for_purchase](player-paid-for-purchase.md) This event is triggered when the second step of the payment process completes, paying for the purchase. @@ -481,12 +424,6 @@ Each event type has a set of properties that are included as part of event's dat - [player_redeemed_coupon](player-redeemed-coupon.md) This event is triggered when a player redeems a coupon. -- [player_removed_title](player-removed-title.md) - This event is triggered when a player account for a title is removed. Note: this event is triggered once per title rather than once per publisher. - -- [player_reported_as_abusive](player-reported-as-abusive.md) - This event is triggered when a player is reported by another player as abusive. - - [player_set_profile_property](player-set-profile-property.md) This event is triggered when PlayFab makes an internal adjustment to a player profile. @@ -499,26 +436,138 @@ Each event type has a set of properties that are included as part of event's dat - [player_statistic_deleted](player-statistic-deleted.md) This event is triggered when a player statistic is deleted. -- [player_tag_added](player-tag-added.md) +- [player_vc_item_purchased](player-vc-item-purchased.md) + This event is triggered when the player makes a purchase using virtual currency. + +- [player_virtual_currency_balance_changed](player-virtual-currency-balance-changed.md) + This event is triggered when a player's virtual currency balance changes. + +## PlayerIdentity + +- [auth_token_validated](PlayerIdentity/auth-token-validated.md) + This event is triggered when an email confirmation link is clicked. + +- [character_created](PlayerIdentity/character-created.md) + This event is triggered when a character is created for the first time. + +- [entity_created](PlayerIdentity/entity-created.md) + This event is triggered when an entity is created. + +- [entity_logged_in](PlayerIdentity/entity-logged-in.md) + This event is triggered when an entity has logged in. + +- [player_added_title](PlayerIdentity/player-added-title.md) + This event is triggered when a player creates a new account for a title. Note: this event is triggered once per title rather than once per publisher. + +- [player_banned](PlayerIdentity/player-banned.md) + This event is triggered when a player is banned. + +- [player_changed_avatar](PlayerIdentity/player-changed-avatar.md) + This event is triggered when a player's avatar URL is changed. + +- [player_completed_password_reset](PlayerIdentity/player-completed-password-reset.md) + This event is triggered when a player completes the password reset process by visiting the link URL that was sent to them and choosing a new password. + +- [player_created](PlayerIdentity/player-created.md) + This event is triggered when a player account is created for the first time. Note: this event is only triggered once per publisher, not once per title. + +- [player_data_exported](PlayerIdentity/player-data-exported.md) + This event is triggered when a player's data is exported. + +- [player_device_info](PlayerIdentity/player-device-info.md) + This event is triggered once after the player logs in based on the settings for your title. + +- [player_displayname_changed](PlayerIdentity/player-displayname-changed.md) + This event is triggered when a player's display name is changed. + +- [player_linked_account](PlayerIdentity/player-linked-account.md) + This event is triggered when a new authentication method is linked to a player's account. + +- [player_logged_in](PlayerIdentity/player-logged-in.md) + This event is triggered when a player logs in. + +- [player_password_reset_link_sent](PlayerIdentity/player-password-reset-link-sent.md) + This event is triggered when a player is sent a link to reset their password. + +- [player_removed_title](PlayerIdentity/player-removed-title.md) + This event is triggered when a player account for a title is removed. Note: this event is triggered once per title rather than once per publisher. + +- [player_reported_as_abusive](PlayerIdentity/player-reported-as-abusive.md) + This event is triggered when a player is reported by another player as abusive. + +- [player_tag_added](PlayerIdentity/player-tag-added.md) This event is triggered when a tag is added to a player profile. -- [player_tag_removed](player-tag-removed.md) +- [player_tag_removed](PlayerIdentity/player-tag-removed.md) This event is triggered when a tag is removed from a player profile. -- [player_unlinked_account](player-unlinked-account.md) +- [player_unlinked_account](PlayerIdentity/player-unlinked-account.md) This event is triggered when an authentication method is unlinked from a player's account. -- [player_updated_contact_email](player-updated-contact-email.md) +- [player_updated_contact_email](PlayerIdentity/player-updated-contact-email.md) This event is triggered when a player updates a contact email on their profile. -- [player_vc_item_purchased](player-vc-item-purchased.md) - This event is triggered when the player makes a purchase using virtual currency. - -- [player_verified_contact_email](player-verified-contact-email.md) +- [player_verified_contact_email](PlayerIdentity/player-verified-contact-email.md) This event is triggered when a contact email is verified for a player. -- [player_virtual_currency_balance_changed](player-virtual-currency-balance-changed.md) - This event is triggered when a player's virtual currency balance changes. +- [title_deleted_master_player](PlayerIdentity/title-deleted-master-player.md) + This event is triggered when a GDPR delete is finished. + +- [title_initiated_player_password_reset](PlayerIdentity/title-initiated-player-password-reset.md) + This event is triggered when a title initiates the account recovery process for a player. + +- [title_profile_view_constraints_changed](PlayerIdentity/title-profile-view-constraints-changed.md) + This event is triggered when a profile view constraint is changed for the title. + +- [entity_deleted](PlayerIdentity/entity-deleted.md) + This event is triggered when an entity is deleted. + +- [logged_in_to_title](PlayerIdentity/logged-in-to-title.md) + This event is triggered when a user logs in to a title. + +- [player_authenticated](PlayerIdentity/player-authenticated.md) + This event is triggered when a player is authenticated. + +- [player_custom_properties_changed](PlayerIdentity/player-custom-properties-changed.md) + This event is triggered when a player's custom properties are changed. + +- [player_identity_link_added](PlayerIdentity/player-identity-link-added.md) + This event is triggered when a player identity link is added. + +- [player_identity_link_removed](PlayerIdentity/player-identity-link-removed.md) + This event is triggered when a player identity link is removed. + +- [player_updated_login_email](PlayerIdentity/player-updated-login-email.md) + This event is triggered when a player updates their login email. + +## PlayerProfile + +- [entity_files_set](PlayerProfile/entity-files-set.md) + This event is triggered when files are attached to an entity. + +- [entity_language_updated](PlayerProfile/entity-language-updated.md) + This event is triggered when the language associated with an entity is changed. + +- [entity_objects_set](PlayerProfile/entity-objects-set.md) + This event is triggered when objects are attached to an entity. + +- [access_policy_updated](PlayerProfile/access-policy-updated.md) + This event is triggered when an access policy is updated. + +- [avatar_url_updated](PlayerProfile/avatar-url-updated.md) + This event is triggered when an avatar URL is updated. + +- [contact_email_updated](PlayerProfile/contact-email-updated.md) + This event is triggered when a contact email is updated. + +- [files_changed](PlayerProfile/files-changed.md) + This event is triggered when files are changed. + +- [language_updated](PlayerProfile/language-updated.md) + This event is triggered when a language setting is updated. + +- [objects_updated](PlayerProfile/objects-updated.md) + This event is triggered when objects are updated. ## Session @@ -536,21 +585,9 @@ Each event type has a set of properties that are included as part of event's dat - [title_client_rate_limited_alert](title-client-rate-limited-alert.md) This event is triggered when a single IP address generates too many API calls to PlayFab and is throttled. -- [title_deleted](title-deleted.md) - This event is triggered when a game title is deleted. - - [title_high_error_rate_alert](title-high-error-rate-alert.md) This event is triggered when a game title experiences a high rate of errors. -- [title_initiated_player_password_reset](title-initiated-player-password-reset.md) - This event is triggered when a title initiates the account recovery process for a player. - -- [title_news_updated](title-news-updated.md) - This event is triggered when a title news is created or updated. - -- [title_profile_view_constraints_changed](title-profile-view-constraints-changed.md) - This event is triggered when a profile view constraint is changed for the title. - - [title_queue_config_updated](title-queue-config-updated.md) This event is triggered when a queue config is changed. @@ -560,15 +597,32 @@ Each event type has a set of properties that are included as part of event's dat - [title_saved_survey](title-saved-survey.md) This event is triggered when a game's survey is saved. -- [title_secret_key_changed](title-secret-key-changed.md) - This event is triggered when a title adds or updates a Secret Key - - [title_statistic_version_changed](title-statistic-version-changed.md) This event is triggered when the version of a statistic changes, causing its leaderboard to reset. - [title_store_updated](title-store-updated.md) This event is triggered when a store is changed. +## TitleData + +- [title_news_updated](TitleData/title-news-updated.md) + This event is triggered when a title news is created or updated. + +- [title_secret_key_changed](TitleData/title-secret-key-changed.md) + This event is triggered when a title adds or updates a Secret Key + +- [title_activated](TitleData/title-activated.md) + This event is triggered when a title is activated. + +- [title_data_override_deleted](TitleData/title-data-override-deleted.md) + This event is triggered when a title data override is deleted. + +- [title_data_updated](TitleData/title-data-updated.md) + This event is triggered when title data is updated. + +- [title_deactivated](TitleData/title-deactivated.md) + This event is triggered when a title is deactivated. + ## Statistics - [statistic_updated](statistic-updated.md) From 56b9dcf588b5511cef1731aec880cf5687443f5c Mon Sep 17 00:00:00 2001 From: Andy McCalib Date: Fri, 13 Feb 2026 13:38:59 -0800 Subject: [PATCH 41/76] Improve token expiration docs for GDK suspend/resume scenarios (#2812) * Improve token expiration docs for GDK suspend/resume scenarios - Rewrite relogin.md to clearly explain when auto-refresh works vs when the title must handle token expiration (expiring-soon vs already-expired) - Add GDK suspend/resume/Quick Resume section with detailed guidance on what happens on resume and how to reconnect multiplayer services - Add IMPORTANT callout that TokenExpiredHandler is essential for GDK - Add code sample showing async re-login with lobby/matchmaking reconnect - Add suspend/resume section to quickstart-gdk.md linking to full docs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Acrolinx scorecard issues in relogin.md Address clarity, consistency, tone, and terminology flags: - Expand GDK acronym on first use - Remove spaces around em dashes - Drop hyphens from re-authenticate, re-login, re-initialize - Replace present perfect tense with simple past/present - Use contractions (cannot -> can't) - Use 'sign-in' instead of 'login' for non-API references - Remove filler word 'strongly' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- playfab-docs/sdks/c/quickstart-gdk.md | 6 ++++ playfab-docs/sdks/c/relogin.md | 43 +++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/playfab-docs/sdks/c/quickstart-gdk.md b/playfab-docs/sdks/c/quickstart-gdk.md index 1240fc2ba..03d22d339 100644 --- a/playfab-docs/sdks/c/quickstart-gdk.md +++ b/playfab-docs/sdks/c/quickstart-gdk.md @@ -80,6 +80,12 @@ Along with an __S_OK__ result, you get back a __PFEntityHandle__. You use this h hr = PFAuthenticationLoginWithXUserGetResult(&async, &entityHandle, loginResultBuffer.size(), loginResultBuffer.data(), &loginResult, nullptr); ``` +## Handling suspend and resume + +GDK games can be suspended for extended periods (for example, via Quick Resume). If the entity token expires during suspension, the SDK detects this on resume and notifies your game. You should register for the **TokenExpiredHandler** early in your game's lifecycle so you can re-authenticate and reconnect services when needed. + +For full details, see [Handling Token Expiration](relogin.md). + ## Service Calls After logging the player in, you can now make calls to the PlayFab backend. Here's an example of a call to get files stored in PlayFab for the current player. diff --git a/playfab-docs/sdks/c/relogin.md b/playfab-docs/sdks/c/relogin.md index 87a83c0ae..0f9d327b1 100644 --- a/playfab-docs/sdks/c/relogin.md +++ b/playfab-docs/sdks/c/relogin.md @@ -3,20 +3,36 @@ title: Handling Token Expiration author: amccalib description: Handling Token Expiration and Relogin in the PlayFab Services SDK ms.author: andmcc -ms.date: 03/03/2023 +ms.date: 02/13/2026 ms.topic: article ms.service: azure-playfab -keywords: playfab, c++, windows, xbox, gdk, login +keywords: playfab, c++, windows, xbox, gdk, login, suspend, resume, quick resume, token refresh ms.localizationpriority: medium --- # Handling Token Expiration -The PlayFab Services SDK automatically attempts to handle relogin and token refresh in this SDK. When a PlayFab entity token expires, the SDK detects the failure and attempts to acquire a new entity token using the handle or token you originally provided to the login request. If this relogin succeeds, the SDK retries the original failed call automatically. Additionally, the **PFEntityHandle** returned by the original login call continues to be valid. +The PlayFab Services SDK includes a background token refresh mechanism that helps keep your player's session active. Understanding how this mechanism works—and when your game needs to take action—is important, especially for Game Development Kit (GDK) titles that support suspend and resume. -## Automatic refresh failure +## How automatic token refresh works -It's possible for automatic token refresh to fail. This failure could be because the handle or token you originally provided to the login request is no longer valid. To handle this scenario, your game can register for a callback to provide a new handle or token and retry the login. Use **PFEntityRegisterTokenExpiredEventHandler** to register for a callback and **PFAuthenticationReLoginWith\*Async** to provide the new handle or token and reattempt the login. +The SDK runs a background worker that periodically checks the player's entity token. If the token is **still valid but approaching expiration** (within one hour of expiry), the SDK automatically reauthenticates using the credentials from the original sign-in call. If this refresh succeeds, the token is updated transparently and the **PFEntityHandle** continues to be valid. No action is required from your game. + +You can observe these silent token refreshes by registering a **PFEntityRegisterTokenRefreshedEventHandler** callback (see [Transparent refresh](#transparent-refresh)). + +## When your game must handle token expiration + +There are scenarios where the SDK **can't** automatically refresh the token: + +- **The token has already expired.** The automatic refresh only works when the token is still valid. If the token is fully expired—for example, after a long suspend/resume cycle—the SDK doesn't attempt an automatic relogin. Instead, it notifies your game via the **TokenExpiredHandler**. +- **The original sign-in credentials are no longer valid.** If the handle or token originally provided to the sign-in request is no longer valid, automatic refresh fails and the **TokenExpiredHandler** is invoked. + +> [!IMPORTANT] +> Registering a **PFEntityTokenExpiredEventHandler** is recommended for all titles and is **essential** for GDK titles that support suspend and resume. Without this handler, your game has no way to recover from an expired token. + +### Registering the TokenExpiredHandler + +Use **PFEntityRegisterTokenExpiredEventHandler** to register for a callback and **PFAuthenticationReLoginWith\*Async** to reauthenticate when the token expires. ```cpp PFRegistrationToken registrationTokenExpired{}; @@ -41,9 +57,24 @@ It's possible for automatic token refresh to fail. This failure could be because }, ®istrationTokenExpired); ``` +## GDK: Suspend, resume, and Quick Resume + +On GDK platforms (Xbox consoles and Windows with the GDK), a game can be suspended for an extended period, such as when the player switches to another game and later returns via Quick Resume. During suspension, the entity token may expire. Because no code runs during suspension, the SDK's periodic background refresh can't keep the token alive. + +### What happens on resume + +When your game resumes, the SDK **immediately** detects the resumed state and checks the entity token. It doesn't wait for the next periodic refresh cycle. If the token expired during the suspend: + +1. The SDK detects the expired token. +2. The **TokenExpiredHandler** callback is invoked. +3. Your game must call **PFAuthenticationReLoginWith\*Async** from the handler to acquire a new token. + +> [!NOTE] +> The token check on resume is triggered as soon as network connectivity is restored. If the network takes a moment to reinitialize after resume, the SDK waits for connectivity before checking the token. No token check is lost. + ## Transparent refresh -If you would like your game to know when the SDK automatically refreshes the player's entity token, you can register for a callback. +If you would like your game to know when the SDK automatically refreshes the player's entity token, you can register for a callback. This handler is invoked when the SDK successfully refreshes a token that was approaching expiration—no action is required from your game. ```cpp PFRegistrationToken registrationTokenRefreshed{}; From 5ad95d1c2c8e16a5f8aed8966f89a5507f4be5d2 Mon Sep 17 00:00:00 2001 From: Sebastian Perez-Delgado <46662157+SebastianPD@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:39:16 -0800 Subject: [PATCH 42/76] Update lobby-and-matchmaking-release-notes.md (#2778) * Update lobby-and-matchmaking-release-notes.md --- .../lobby-and-matchmaking-release-notes.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md index 27fead97f..6c294494f 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md @@ -12,6 +12,14 @@ ms.localizationpriority: medium # PlayFab Multiplayer C++ SDK release notes +## 1.8.5 + +Jan 21, 2026 + +### Bug fixes + +- Hide symbols in iOS platform to prevent symbol clashing. This is an iOS only release. + ## 1.8.4 Nov 5, 2025 From eeb0ef6ee1f3dcc44ae226a3946671e025dc0401 Mon Sep 17 00:00:00 2001 From: Scott Munro Date: Fri, 13 Feb 2026 17:04:29 -0800 Subject: [PATCH 43/76] PFMultiplayer v1.8.6: Update relnotes and ref docs (#2815) * release notes * update ref doc error code values --- .../lobby-and-matchmaking-release-notes.md | 11 +++++++++++ .../pfmultiplayererrors.md | 7 ++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md index 6c294494f..4eb7a6d83 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md @@ -12,6 +12,17 @@ ms.localizationpriority: medium # PlayFab Multiplayer C++ SDK release notes +## 1.8.6 + +Feb 13, 2026 + +### Bug fixes + +- Fixed an issue where 24 hours after the first lobby or matchmaking attempt, if the library has not been cleaned up, it may fail to create subsequent lobbies, join subsequent lobbies, subscribe to lobby invitations, or create subsequent matchmaking tickets. +- Fixed an issue where PlayFab Lobby service failures could cause the PlayFabMultiplayer library to be unable to create new lobbies until it after [PFMultiplayerUninitialize()](../playfabmultiplayerreference-cpp/pfmultiplayer/functions/pfmultiplayeruninitialize.md) was called and the library was reinitialized with PFMultiplayerInitialize +- Fixed an issue on non-GDK platforms where the library would keep internal process task queue memory allocated after the library had been cleaned up with [PFMultiplayerUninitialize()](../playfabmultiplayerreference-cpp/pfmultiplayer/functions/pfmultiplayeruninitialize.md). +- Fixed an issue where several PubSub service errors were being collapsed into one generic HTTP 4XX error message, [0x89236409](../playfabmultiplayerreference-cpp/pfmultiplayererrors.md). Now, the library provides different error codes for different service errors which makes it easier to diagnose and troubleshoot. + ## 1.8.5 Jan 21, 2026 diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayererrors.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayererrors.md index 1e2a7982e..224b754f5 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayererrors.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayererrors.md @@ -5,7 +5,7 @@ description: "Error codes used by the PlayFab Multiplayer, Lobby, and Matchmakin ms.author: scmunro ms.topic: reference ms.service: azure-playfab -ms.date: 01/23/2026 +ms.date: 02/13/2026 --- # PlayFab Multiplayer C++ SDK Error Codes @@ -170,6 +170,11 @@ For additional guidance on handling these errors, check out [Handling Lobby and | 0x89236620 | -1994168800 | The PubSub service failed to deliver a subscription confirmation within a reasonable timeout. | | 0x89236621 | -1994168799 | The PubSub service failed due to lack of authentication credentials to a specific resource. | | 0x89236622 | -1994168798 | Failed to access PubSub services; check credentials. | +| 0x89236623 | -1994168797 | The provided PlayFab title does not have PubSub services enabled. | +| 0x89236624 | -1994168796 | The PubSub service is throttling the client due to exceeding the rate limit. | +| 0x89236625 | -1994168795 | The PubSub service could not complete the request because a connection for the specified entity was not found. | +| 0x89236626 | -1994168794 | PlayFab services rejected our PubSub connection handle as invalid. | +| 0x89236627 | -1994168793 | The entity has exceeded their limit of concurrent PubSub subscriptions. | ## Global HRESULT error codes From fb900cceb2bb1eb7cf1ee94b466c523edf39b8ed Mon Sep 17 00:00:00 2001 From: ronnyparedesc <113482725+ronnyparedesc@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:07:29 -0800 Subject: [PATCH 44/76] PlayStream event documentation update for GameSaves, Leaderboards, Matchmaking (#2791) * Add GameSave documentation * LB events * Fix common properties * Fix references * Matchmaking events * Modify author and metadata in title_statistic_deleted Updated author and metadata for title_statistic_deleted event. * remove internal namespaces from documentation * remove duplicates * updated matchmaking PlayStream events * added event to new statistics folder * update matchmaking events * update properties and remove unncessary payloads * Change author from jenelleb to anaislawson Updated author information in title_queue_config_updated event documentation. * remove unlinked files * remove duplicate matchmaking found --------- Co-authored-by: anaisnlawson --- .../gamesave-version-finalized.md | 4 +- .../gamesave-version-marked-known-good.md | 2 +- .../character-statistic-changed.md | 2 +- .../character-statistic-deleted.md | 2 +- ...ntity-rank-on-leaderboard-version-ended.md | 2 +- .../leaderboard-version-ended.md | 2 +- .../player-ranked-on-leaderboard-version.md | 6 +- .../player-statistic-changed.md | 4 +- .../player-statistic-deleted.md | 2 +- .../Leaderboards/title-statistic-deleted.md | 26 +++++ .../title-statistic-version-changed.md | 4 +- .../events/Matchmaking/match-found.md | 27 +++++ .../events/Matchmaking/ticket-completed.md | 33 ++++++ .../title-queue-config-updated.md | 10 +- .../events/Matchmaking/user-ticket-invited.md | 26 +++++ .../{ => Statistics}/statistic-updated.md | 2 +- playfab-docs/api-references/events/index.md | 106 ++++++++++++++---- .../events/matchmaking-match-found.md | 29 ----- .../events/matchmaking-ticket-completed.md | 27 ----- .../matchmaking-user-ticket-completed.md | 29 ----- .../events/matchmaking-user-ticket-invite.md | 29 ----- playfab-docs/api-references/toc.yml | 12 +- 22 files changed, 221 insertions(+), 165 deletions(-) rename playfab-docs/api-references/events/{ => GameSave}/gamesave-version-finalized.md (80%) rename playfab-docs/api-references/events/{ => GameSave}/gamesave-version-marked-known-good.md (89%) rename playfab-docs/api-references/events/{ => Leaderboards}/character-statistic-changed.md (91%) rename playfab-docs/api-references/events/{ => Leaderboards}/character-statistic-deleted.md (90%) rename playfab-docs/api-references/events/{ => Leaderboards}/entity-rank-on-leaderboard-version-ended.md (91%) rename playfab-docs/api-references/events/{ => Leaderboards}/leaderboard-version-ended.md (89%) rename playfab-docs/api-references/events/{ => Leaderboards}/player-ranked-on-leaderboard-version.md (74%) rename playfab-docs/api-references/events/{ => Leaderboards}/player-statistic-changed.md (79%) rename playfab-docs/api-references/events/{ => Leaderboards}/player-statistic-deleted.md (91%) create mode 100644 playfab-docs/api-references/events/Leaderboards/title-statistic-deleted.md rename playfab-docs/api-references/events/{ => Leaderboards}/title-statistic-version-changed.md (74%) create mode 100644 playfab-docs/api-references/events/Matchmaking/match-found.md create mode 100644 playfab-docs/api-references/events/Matchmaking/ticket-completed.md rename playfab-docs/api-references/events/{ => Matchmaking}/title-queue-config-updated.md (73%) create mode 100644 playfab-docs/api-references/events/Matchmaking/user-ticket-invited.md rename playfab-docs/api-references/events/{ => Statistics}/statistic-updated.md (92%) delete mode 100644 playfab-docs/api-references/events/matchmaking-match-found.md delete mode 100644 playfab-docs/api-references/events/matchmaking-ticket-completed.md delete mode 100644 playfab-docs/api-references/events/matchmaking-user-ticket-completed.md delete mode 100644 playfab-docs/api-references/events/matchmaking-user-ticket-invite.md diff --git a/playfab-docs/api-references/events/gamesave-version-finalized.md b/playfab-docs/api-references/events/GameSave/gamesave-version-finalized.md similarity index 80% rename from playfab-docs/api-references/events/gamesave-version-finalized.md rename to playfab-docs/api-references/events/GameSave/gamesave-version-finalized.md index ef5e2e217..d885ea78c 100644 --- a/playfab-docs/api-references/events/gamesave-version-finalized.md +++ b/playfab-docs/api-references/events/GameSave/gamesave-version-finalized.md @@ -27,8 +27,8 @@ This event is triggered when a game save version is finalized with all the files |TotalFileCount|Int32|The total number of files that were included in the finalized game save version.| |TotalSizeBytes|Int64|The total size in bytes of the finalized game save version, including all files.| |IsGeneratedByRollback|Boolean|Whether the version was generated and finalized by a rollback operation.| -|Conflict|[GameSaveConflict](data-types/gamesaveconflict.md)|Data about any conflict that occurred during the finalization of the game save version. This will usually be null if the version was not finalized during a conflict resolution operation.| +|Conflict|[GameSaveConflict](../data-types/gamesaveconflict.md)|Data about any conflict that occurred during the finalization of the game save version. This will usually be null if the version was not finalized during a conflict resolution operation.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/gamesave-version-marked-known-good.md b/playfab-docs/api-references/events/GameSave/gamesave-version-marked-known-good.md similarity index 89% rename from playfab-docs/api-references/events/gamesave-version-marked-known-good.md rename to playfab-docs/api-references/events/GameSave/gamesave-version-marked-known-good.md index f55a07650..0bf2fbc91 100644 --- a/playfab-docs/api-references/events/gamesave-version-marked-known-good.md +++ b/playfab-docs/api-references/events/GameSave/gamesave-version-marked-known-good.md @@ -23,4 +23,4 @@ This event is triggered when a game save version is marked as known good. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/character-statistic-changed.md b/playfab-docs/api-references/events/Leaderboards/character-statistic-changed.md similarity index 91% rename from playfab-docs/api-references/events/character-statistic-changed.md rename to playfab-docs/api-references/events/Leaderboards/character-statistic-changed.md index 3a8fe5345..4d0c696fc 100644 --- a/playfab-docs/api-references/events/character-statistic-changed.md +++ b/playfab-docs/api-references/events/Leaderboards/character-statistic-changed.md @@ -27,4 +27,4 @@ This event is triggered when a character statistic is changed. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/character-statistic-deleted.md b/playfab-docs/api-references/events/Leaderboards/character-statistic-deleted.md similarity index 90% rename from playfab-docs/api-references/events/character-statistic-deleted.md rename to playfab-docs/api-references/events/Leaderboards/character-statistic-deleted.md index 31c7b4b80..f28c6d970 100644 --- a/playfab-docs/api-references/events/character-statistic-deleted.md +++ b/playfab-docs/api-references/events/Leaderboards/character-statistic-deleted.md @@ -25,4 +25,4 @@ This event is triggered when a character statistic is deleted. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/entity-rank-on-leaderboard-version-ended.md b/playfab-docs/api-references/events/Leaderboards/entity-rank-on-leaderboard-version-ended.md similarity index 91% rename from playfab-docs/api-references/events/entity-rank-on-leaderboard-version-ended.md rename to playfab-docs/api-references/events/Leaderboards/entity-rank-on-leaderboard-version-ended.md index 367c5ff4a..4241e0017 100644 --- a/playfab-docs/api-references/events/entity-rank-on-leaderboard-version-ended.md +++ b/playfab-docs/api-references/events/Leaderboards/entity-rank-on-leaderboard-version-ended.md @@ -26,4 +26,4 @@ This event is triggered when a leaderboard version is reset to a new version for ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/leaderboard-version-ended.md b/playfab-docs/api-references/events/Leaderboards/leaderboard-version-ended.md similarity index 89% rename from playfab-docs/api-references/events/leaderboard-version-ended.md rename to playfab-docs/api-references/events/Leaderboards/leaderboard-version-ended.md index e661453da..dd3e33bdc 100644 --- a/playfab-docs/api-references/events/leaderboard-version-ended.md +++ b/playfab-docs/api-references/events/Leaderboards/leaderboard-version-ended.md @@ -24,4 +24,4 @@ This event is triggered when a leaderboard version is reset to a new version for ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/player-ranked-on-leaderboard-version.md b/playfab-docs/api-references/events/Leaderboards/player-ranked-on-leaderboard-version.md similarity index 74% rename from playfab-docs/api-references/events/player-ranked-on-leaderboard-version.md rename to playfab-docs/api-references/events/Leaderboards/player-ranked-on-leaderboard-version.md index 2b3cbfbac..dde7d02f2 100644 --- a/playfab-docs/api-references/events/player-ranked-on-leaderboard-version.md +++ b/playfab-docs/api-references/events/Leaderboards/player-ranked-on-leaderboard-version.md @@ -18,13 +18,13 @@ This event is triggered for the top-ranked players on a leaderboard when the lea |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|LeaderboardSource|[LeaderboardSource](data-types/leaderboardsource.md)|Source of the values for the leaderboard.| +|LeaderboardSource|[LeaderboardSource](../data-types/leaderboardsource.md)|Source of the values for the leaderboard.| |Rank|uint32|Player's rank on the leaderboard.| |TitleId|String|The ID of the title to which this player event applies.| |Value|int32|Player's leaderboard value.| |Version|uint32|Version of the leaderboard on which the player is ranked. For player statistic leaderboards, this matches the version of the statistic.| -|VersionChangeBehavior|[LeaderboardVersionChangeBehavior](data-types/leaderboardversionchangebehavior.md)|Behavior with respect to the leaderboard values when the version changed.| +|VersionChangeBehavior|[LeaderboardVersionChangeBehavior](../data-types/leaderboardversionchangebehavior.md)|Behavior with respect to the leaderboard values when the version changed.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/player-statistic-changed.md b/playfab-docs/api-references/events/Leaderboards/player-statistic-changed.md similarity index 79% rename from playfab-docs/api-references/events/player-statistic-changed.md rename to playfab-docs/api-references/events/Leaderboards/player-statistic-changed.md index 55a3c7c37..37645a98a 100644 --- a/playfab-docs/api-references/events/player-statistic-changed.md +++ b/playfab-docs/api-references/events/Leaderboards/player-statistic-changed.md @@ -18,7 +18,7 @@ This event is triggered when a player statistic is changed. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|AggregationMethod|[StatisticAggregationMethod](data-types/statisticaggregationmethod.md)|Aggregation method applied for calculating the new value of the statistic.| +|AggregationMethod|[StatisticAggregationMethod](../data-types/statisticaggregationmethod.md)|Aggregation method applied for calculating the new value of the statistic.| |StatisticId|uint32|Unique ID of the statistic that changed.| |StatisticName|String|Name of the statistic that changed.| |StatisticPreviousValue|int32|Old value of the statistic, before the change.| @@ -28,4 +28,4 @@ This event is triggered when a player statistic is changed. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/player-statistic-deleted.md b/playfab-docs/api-references/events/Leaderboards/player-statistic-deleted.md similarity index 91% rename from playfab-docs/api-references/events/player-statistic-deleted.md rename to playfab-docs/api-references/events/Leaderboards/player-statistic-deleted.md index b3ef4ce1d..cd787f919 100644 --- a/playfab-docs/api-references/events/player-statistic-deleted.md +++ b/playfab-docs/api-references/events/Leaderboards/player-statistic-deleted.md @@ -26,4 +26,4 @@ This event is triggered when a player statistic is deleted. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/Leaderboards/title-statistic-deleted.md b/playfab-docs/api-references/events/Leaderboards/title-statistic-deleted.md new file mode 100644 index 000000000..19f4ec5d1 --- /dev/null +++ b/playfab-docs/api-references/events/Leaderboards/title-statistic-deleted.md @@ -0,0 +1,26 @@ +--- +title: title_statistic_deleted +author: anaislawson +description: title_statistic_deleted event. +ms.author: anaislawson +ms.date: 02/05/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# title_statistic_deleted + +This event is triggered when a title statistic is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|StatisticName|String|Unique name of the statistic.| +|StatisticVersion|uint32|Version of the statistic.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-statistic-version-changed.md b/playfab-docs/api-references/events/Leaderboards/title-statistic-version-changed.md similarity index 74% rename from playfab-docs/api-references/events/title-statistic-version-changed.md rename to playfab-docs/api-references/events/Leaderboards/title-statistic-version-changed.md index 370825e4f..4a06fdc96 100644 --- a/playfab-docs/api-references/events/title-statistic-version-changed.md +++ b/playfab-docs/api-references/events/Leaderboards/title-statistic-version-changed.md @@ -18,11 +18,11 @@ This event is triggered when the version of a statistic changes, causing its lea |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|ScheduledResetInterval|[StatisticResetIntervalOption](data-types/statisticresetintervaloption.md)|The interval on which the statistic leaderboard was configured to reset, if any.| +|ScheduledResetInterval|[StatisticResetIntervalOption](../data-types/statisticresetintervaloption.md)|The interval on which the statistic leaderboard was configured to reset, if any.| |ScheduledResetTime|DateTime|The time at which the statistic leaderboard was configured to reset, if any.| |StatisticName|String|Unique name of the statistic.| |StatisticVersion|uint32|Version of the statistic, following the update.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Matchmaking/match-found.md b/playfab-docs/api-references/events/Matchmaking/match-found.md new file mode 100644 index 000000000..c0b51ba40 --- /dev/null +++ b/playfab-docs/api-references/events/Matchmaking/match-found.md @@ -0,0 +1,27 @@ +--- +title: match_found +author: anaislawson +description: match_found event. +ms.author: anaislawson +ms.date: 02/05/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events, matchmaking +ms.localizationpriority: medium +--- + +# match_found + +This event is triggered when matchmaking successfully forms a match for a set of tickets. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|MatchId|String|The unique identifier for the match that was created.| +|QueueName|String|The name of the matchmaking queue in which the match was formed.| +|TicketIds|String[]|An array of ticket IDs that were matched together to form the match.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Matchmaking/ticket-completed.md b/playfab-docs/api-references/events/Matchmaking/ticket-completed.md new file mode 100644 index 000000000..d0e5f5eca --- /dev/null +++ b/playfab-docs/api-references/events/Matchmaking/ticket-completed.md @@ -0,0 +1,33 @@ +--- +title: ticket_completed +author: anaislawson +description: ticket_completed event. +ms.author: anaislawson +ms.date: 02/05/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events, matchmaking +ms.localizationpriority: medium +--- + +# ticket_completed + +This event is triggered when a matchmaking ticket reaches a terminal state (for example, it is matched or canceled). + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|CancellationReason|String|If the ticket result is Canceled then this string provides the reason why the ticket was canceled otherwise it is null. Possible values: Requested, Internal, Timeout, ServerAllocationFailed.| +|CompletionTime|DateTime|Time at which this ticket was completed.| +|CreationTime|DateTime|Time at which this ticket was created.| +|MatchId|String|The identifier for the match that the ticket got matched into. This field is only set if the ticket got matched otherwise it will be null.| +|QueueName|String|The name of the queue the ticket was created in.| +|Result|String|The final state of the ticket. It could be Matched or Canceled.| +|SubmissionTime|DateTime|Time at which this ticket was submitted into the matchmaking queue.| +|TicketEntities|[EntityKey](../data-types/entitykey.md)[]|The list of entities that are part of this ticket.| +|TicketId|String|Id of the ticket that was completed.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/title-queue-config-updated.md b/playfab-docs/api-references/events/Matchmaking/title-queue-config-updated.md similarity index 73% rename from playfab-docs/api-references/events/title-queue-config-updated.md rename to playfab-docs/api-references/events/Matchmaking/title-queue-config-updated.md index 6a9394c68..cf324273c 100644 --- a/playfab-docs/api-references/events/title-queue-config-updated.md +++ b/playfab-docs/api-references/events/Matchmaking/title-queue-config-updated.md @@ -1,12 +1,12 @@ --- title: title_queue_config_updated -author: joannaleecy +author: anaislawson description: title_queue_config_updated event. -ms.author: jenelleb -ms.date: 02/19/2019 +ms.author: anaislawson +ms.date: 02/10/2026 ms.topic: article ms.service: azure-playfab -keywords: playfab, playstream events +keywords: playfab, playstream events, matchmaking ms.localizationpriority: medium --- @@ -25,4 +25,4 @@ This event is triggered when a queue config is changed. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Matchmaking/user-ticket-invited.md b/playfab-docs/api-references/events/Matchmaking/user-ticket-invited.md new file mode 100644 index 000000000..ec1b31e5a --- /dev/null +++ b/playfab-docs/api-references/events/Matchmaking/user-ticket-invited.md @@ -0,0 +1,26 @@ +--- +title: user_ticket_invited +author: anaislawson +description: user_ticket_invited event. +ms.author: anaislawson +ms.date: 02/10/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events, matchmaking +ms.localizationpriority: medium +--- + +# user_ticket_invited + +This event is triggered when a user is invited to a ticket. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|QueueName|String|The name of the queue the ticket was created in.| +|TicketId|String|Id of the ticket that the user was invited to.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/statistic-updated.md b/playfab-docs/api-references/events/Statistics/statistic-updated.md similarity index 92% rename from playfab-docs/api-references/events/statistic-updated.md rename to playfab-docs/api-references/events/Statistics/statistic-updated.md index c97dd19e0..b7122e375 100644 --- a/playfab-docs/api-references/events/statistic-updated.md +++ b/playfab-docs/api-references/events/Statistics/statistic-updated.md @@ -28,4 +28,4 @@ This event is triggered when a statistic is updated for a given entity. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index a84b4869d..02940d8aa 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -158,6 +158,17 @@ Each event type has a set of properties that are included as part of event's dat - [group_updated](Groups/group-updated.md) This event is triggered when an entity group is updated. +- [studio_created](studio-created.md) + This event is triggered when a studio is created. + +- [studio_user_added](studio-user-added.md) + This event is triggered when a user accepts a studio invitation. + +- [studio_user_invited](studio-user-invited.md) + This event is triggered when a user is invited to a studio. + +- [studio_user_removed](studio-user-removed.md) + This event is triggered when a user is removed from a studio. - [members_added](Groups/members-added.md) This event is triggered when members are added to a group. @@ -212,24 +223,25 @@ Each event type has a set of properties that are included as part of event's dat - [group_deleted](group-deleted.md) This event is triggered when an entity group is deleted. -- [matchmaking_match_found](matchmaking-match-found.md) - This event is triggered when a group of tickets are matched together. - -- [matchmaking_ticket_completed](matchmaking-ticket-completed.md) - This event is triggered when a matchmaking ticket reaches a completion state. - -- [matchmaking_user_ticket_completed](matchmaking-user-ticket-completed.md) - This event is sent to each of the users in the completed ticket. - -- [matchmaking_user_ticket_invite](matchmaking-user-ticket-invite.md) - This event is triggered when a ticket with an invited user is created. The event will be sent to the invited user. - - [tenancy_connector_onboard](tenancy-connector-onboard.md) This event is triggered when a tenancy connector is onboarded. - [studio_tier_updated](studio-tier-updated.md) This event is triggered when a studio tier is updated. +## Matchmaking +- [title_queue_config_updated](Matchmaking/title-queue-config-updated.md) + This event is triggered when a queue config is changed. + +- [match_found](Matchmaking/match-found.md) + This event is triggered when a match is found. + +- [ticket_completed](Matchmaking/ticket-completed.md) + This event is triggered when a ticket is completed. + +- [user_ticket_invited](Matchmaking/user-ticket-invited.md) + This event is triggered when a user is invited to a ticket. + ## Multiplayer Servers - [build_alias_created](build-alias-created.md) @@ -342,12 +354,6 @@ Each event type has a set of properties that are included as part of event's dat - [character_inventory_item_added](character-inventory-item-added.md) This event is triggered when an item is granted to a character. -- [character_statistic_changed](character-statistic-changed.md) - This event is triggered when a character statistic is changed. - -- [character_statistic_deleted](character-statistic-deleted.md) - This event is triggered when a character statistic is deleted. - - [character_vc_item_purchased](character-vc-item-purchased.md) This event is triggered when the character makes a purchase using virtual currency. @@ -379,10 +385,10 @@ Each event type has a set of properties that are included as part of event's dat ## GameSave -- [gamesave_version_finalized](gamesave-version-finalized.md) +- [gamesave_version_finalized](GameSave/gamesave-version-finalized.md) This event is triggered when a game save version is finalized with all the files fully uploaded. -- [gamesave_version_marked_known_good](gamesave-version-marked-known-good.md) +- [gamesave_version_marked_known_good](GameSave/gamesave-version-marked-known-good.md) This event is triggered when a game save version is marked as known good. ## Partner @@ -492,6 +498,8 @@ Each event type has a set of properties that are included as part of event's dat - [player_removed_title](PlayerIdentity/player-removed-title.md) This event is triggered when a player account for a title is removed. Note: this event is triggered once per title rather than once per publisher. +- [player_realmoney_purchase](player-realmoney-purchase.md) + This event is triggered when a player makes a real money purchase, and generates revenue for the game. - [player_reported_as_abusive](PlayerIdentity/player-reported-as-abusive.md) This event is triggered when a player is reported by another player as abusive. @@ -519,6 +527,8 @@ Each event type has a set of properties that are included as part of event's dat - [title_profile_view_constraints_changed](PlayerIdentity/title-profile-view-constraints-changed.md) This event is triggered when a profile view constraint is changed for the title. +- [player_tag_added](player-tag-added.md) + This event is triggered when a tag is added to a player profile. - [entity_deleted](PlayerIdentity/entity-deleted.md) This event is triggered when an entity is deleted. @@ -588,7 +598,25 @@ Each event type has a set of properties that are included as part of event's dat - [title_high_error_rate_alert](title-high-error-rate-alert.md) This event is triggered when a game title experiences a high rate of errors. -- [title_queue_config_updated](title-queue-config-updated.md) +- [title_initiated_player_password_reset](title-initiated-player-password-reset.md) + This event is triggered when a title initiates the account recovery process for a player. + +- [title_limit_changed](title-limit-changed.md) + This event is triggered when a title changes a service limit. + +- [title_news_updated](title-news-updated.md) + This event is triggered when a title news is created or updated. + +- [title_permission_policy_changed](title-permission-policy-changed.md) + This event is triggered when an update occurs to a a title's permission policies. + +- [title_profile_view_constraints_changed](title-profile-view-constraints-changed.md) + This event is triggered when a profile view constraint is changed for the title. + +- [title_published_cloudscript](title-published-cloudscript.md) + An inactive revision of CloudScript has been made into the active 'live' version. + +- [title_queue_config_updated](Matchmaking/title-queue-config-updated.md) This event is triggered when a queue config is changed. - [title_requested_limit_change](title-requested-limit-change.md) @@ -597,6 +625,15 @@ Each event type has a set of properties that are included as part of event's dat - [title_saved_survey](title-saved-survey.md) This event is triggered when a game's survey is saved. +- [title_scheduled_cloudscript_executed](title-scheduled-cloudscript-executed.md) + This event is triggered when a CloudScript function is run by a scheduled task. + +- [title_secret_key_changed](title-secret-key-changed.md) + This event is triggered when a title adds or updates a Secret Key + +- [title_started_task](title-started-task.md) + This event is triggered when a task is scheduled to run. + - [title_statistic_version_changed](title-statistic-version-changed.md) This event is triggered when the version of a statistic changes, causing its leaderboard to reset. @@ -625,13 +662,34 @@ Each event type has a set of properties that are included as part of event's dat ## Statistics -- [statistic_updated](statistic-updated.md) +- [statistic_updated](Statistics/statistic-updated.md) This event is triggered when a statistic is updated. ## Leaderboards -- [leaderboard_version_ended](leaderboard-version-ended.md) +- [character_statistic_changed](Leaderboards/character-statistic-changed.md) + This event is triggered when a character statistic is changed. + +- [character_statistic_deleted](Leaderboards/character-statistic-deleted.md) + This event is triggered when a character statistic is deleted. + +- [entity_rank_on_leaderboard_version_ended](Leaderboards/entity-rank-on-leaderboard-version-ended.md) This event is triggered when a leaderboard version is reset -- [entity_rank_on_leaderboard_version_ended](entity-rank-on-leaderboard-version-ended.md) +- [leaderboard_version_ended](Leaderboards/leaderboard-version-ended.md) This event is triggered when a leaderboard version is reset + +- [player_ranked_on_leaderboard_version](Leaderboards/player-ranked-on-leaderboard-version.md) + This event is triggered for the top-ranked players on a leaderboard when the leaderboard version changes (e.g. when a leaderboard statistic version is incremented). The maximum number of leaderboard entries for which the event is generated is controlled by the "Leaderboard version change top rank events sent" title limit. + +- [player_statistic_changed](Leaderboards/player-statistic-changed.md) + This event is triggered when a player statistic is changed. + +- [player_statistic_deleted](Leaderboards/player-statistic-deleted.md) + This event is triggered when a player statistic is deleted. + +- [title_statistic_version_changed](Leaderboards/title-statistic-version-changed.md) + This event is triggered when the version of a statistic changes, causing its leaderboard to reset. + +- [title_statistic_deleted](Leaderboards/title-statistic-deleted.md) + This event is triggered when a title statistic is deleted. diff --git a/playfab-docs/api-references/events/matchmaking-match-found.md b/playfab-docs/api-references/events/matchmaking-match-found.md deleted file mode 100644 index 9f459cc97..000000000 --- a/playfab-docs/api-references/events/matchmaking-match-found.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: matchmaking_match_found -author: joannaleecy -description: matchmaking_match_found event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# matchmaking_match_found - -This event is triggered when a group of tickets are matched together. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[MatchmakingMatchFoundPayload](data-types/matchmakingmatchfoundpayload.md)|Payload that this entity is a child of.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] - - diff --git a/playfab-docs/api-references/events/matchmaking-ticket-completed.md b/playfab-docs/api-references/events/matchmaking-ticket-completed.md deleted file mode 100644 index fe09133df..000000000 --- a/playfab-docs/api-references/events/matchmaking-ticket-completed.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: matchmaking_ticket_completed -author: joannaleecy -description: matchmaking_ticket_completed event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# matchmaking_ticket_completed - -This event is triggered when a matchmaking ticket reaches a completion state. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[MatchmakingTicketCompletePayload](data-types/matchmakingticketcompletepayload.md)|Payload that this entity is a child of.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/matchmaking-user-ticket-completed.md b/playfab-docs/api-references/events/matchmaking-user-ticket-completed.md deleted file mode 100644 index ed9ca6a95..000000000 --- a/playfab-docs/api-references/events/matchmaking-user-ticket-completed.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: matchmaking_user_ticket_completed -author: joannaleecy -description: matchmaking_user_ticket_completed event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# matchmaking_user_ticket_completed - -This event is triggered when a matchmaking ticket reaches a completion state. This event is sent to each of the users in the completed ticket - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[MatchmakingUserTicketCompletePayload](data-types/matchmakinguserticketcompletepayload.md)|Payload that this entity is a child of.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] - - diff --git a/playfab-docs/api-references/events/matchmaking-user-ticket-invite.md b/playfab-docs/api-references/events/matchmaking-user-ticket-invite.md deleted file mode 100644 index bdade1cd4..000000000 --- a/playfab-docs/api-references/events/matchmaking-user-ticket-invite.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: matchmaking_user_ticket_invite -author: joannaleecy -description: matchmaking_user_ticket_invite event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# matchmaking_user_ticket_invite - -This event is triggered when a ticket with an invited user is created. The event will be sent to the invited user. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[MatchmakingUserTicketInvitePayload](data-types/matchmakinguserticketinvitepayload.md)|Payload that this entity is a child of.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] - - diff --git a/playfab-docs/api-references/toc.yml b/playfab-docs/api-references/toc.yml index 3bad324b8..eee939f01 100644 --- a/playfab-docs/api-references/toc.yml +++ b/playfab-docs/api-references/toc.yml @@ -32,9 +32,9 @@ - name: character_inventory_item_added href: events/character-inventory-item-added.md - name: character_statistic_changed - href: events/character-statistic-changed.md + href: events/Leaderboards/character-statistic-changed.md - name: character_statistic_deleted - href: events/character-statistic-deleted.md + href: events/Leaderboards/character-statistic-deleted.md - name: character_vc_item_purchased href: events/character-vc-item-purchased.md - name: character_virtual_currency_balance_changed @@ -216,7 +216,7 @@ - name: player_photon_session_authenticated href: events/player-photon-session-authenticated.md - name: player_ranked_on_leaderboard_version - href: events/player-ranked-on-leaderboard-version.md + href: events/Leaderboards/player-ranked-on-leaderboard-version.md - name: player_realmoney_purchase href: events/player-realmoney-purchase.md - name: player_receipt_validation @@ -234,9 +234,9 @@ - name: player_started_purchase href: events/player-started-purchase.md - name: player_statistic_changed - href: events/player-statistic-changed.md + href: events/Leaderboards/player-statistic-changed.md - name: player_statistic_deleted - href: events/player-statistic-deleted.md + href: events/Leaderboards/player-statistic-deleted.md - name: player_tag_added href: events/player-tag-added.md - name: player_tag_removed @@ -322,7 +322,7 @@ - name: title_started_task href: events/title-started-task.md - name: title_statistic_version_changed - href: events/title-statistic-version-changed.md + href: events/Leaderboards/title-statistic-version-changed.md - name: title_store_updated href: events/title-store-updated.md - name: title_updated_task From e9951ab598087a0a02274bc45f0aad7c657a98a5 Mon Sep 17 00:00:00 2001 From: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Date: Wed, 18 Feb 2026 09:13:10 -0800 Subject: [PATCH 45/76] pf-review-edits-pr-2778-02-17-2026-01 (#2818) --- .../lobby-and-matchmaking-release-notes.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md index 4eb7a6d83..ec64b7acd 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md @@ -14,18 +14,18 @@ ms.localizationpriority: medium ## 1.8.6 -Feb 13, 2026 +February 13, 2026 ### Bug fixes -- Fixed an issue where 24 hours after the first lobby or matchmaking attempt, if the library has not been cleaned up, it may fail to create subsequent lobbies, join subsequent lobbies, subscribe to lobby invitations, or create subsequent matchmaking tickets. +- Fixed an issue where 24 hours after the first lobby or matchmaking attempt, if the library has not been cleaned up, it might fail to create subsequent lobbies, join subsequent lobbies, subscribe to lobby invitations, or create subsequent matchmaking tickets. - Fixed an issue where PlayFab Lobby service failures could cause the PlayFabMultiplayer library to be unable to create new lobbies until it after [PFMultiplayerUninitialize()](../playfabmultiplayerreference-cpp/pfmultiplayer/functions/pfmultiplayeruninitialize.md) was called and the library was reinitialized with PFMultiplayerInitialize - Fixed an issue on non-GDK platforms where the library would keep internal process task queue memory allocated after the library had been cleaned up with [PFMultiplayerUninitialize()](../playfabmultiplayerreference-cpp/pfmultiplayer/functions/pfmultiplayeruninitialize.md). - Fixed an issue where several PubSub service errors were being collapsed into one generic HTTP 4XX error message, [0x89236409](../playfabmultiplayerreference-cpp/pfmultiplayererrors.md). Now, the library provides different error codes for different service errors which makes it easier to diagnose and troubleshoot. ## 1.8.5 -Jan 21, 2026 +January 21, 2026 ### Bug fixes @@ -33,7 +33,7 @@ Jan 21, 2026 ## 1.8.4 -Nov 5, 2025 +November 5, 2025 ### Bug fixes @@ -41,7 +41,7 @@ Nov 5, 2025 ## 1.8.3 -Oct 10, 2025 +October 10, 2025 ### Bug fixes @@ -51,7 +51,7 @@ Oct 10, 2025 ## 1.8.2 -Sep 5, 2025 +September 5, 2025 ### Bug fixes @@ -64,7 +64,7 @@ Sep 5, 2025 ## 1.8.1 -Aug 20, 2025 +August 20, 2025 ### Bug fixes @@ -270,7 +270,7 @@ August 14, 2023 ### Bug fixes -- Fixed an issue where the library may crash while handling a change notification. +- Fixed an issue where the library might crash while handling a change notification. - Added new [PFLobbyMemberCountRemainingSearchKey](../playfabmultiplayerreference-cpp/pflobby/constants/pflobbysearchkeys.md) constant to make it easier to search for and sort lobbies based on their remaining member counts. ## 1.6.2 From eab4d62fa81d094bd5b1cd6b0ac0f89a1a379525 Mon Sep 17 00:00:00 2001 From: Andy McCalib Date: Wed, 18 Feb 2026 09:22:14 -0800 Subject: [PATCH 46/76] C SDK doc alignment: fix inaccuracies, add missing pages (#2814) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * C SDK doc alignment: fix inaccuracies, add missing pages - tracing.md: add PFTraceEnableTraceToFile section - memory.md: fix init sequence (add PFInitialize/PFUninitializeAsync) - eventpipeline.md: add defaults table per pipeline type, handle lifecycle - http-config.md: new page covering PFHttpConfig.h (retry + compression) - lifecycle.md: new page for full init/shutdown sequence + ServiceConfig - entity-handles.md: new page for PFEntity handle lifecycle + API reference Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move Pipeline handle lifecycle above See also section Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix title entity API scope: not limited to Server-prefixed calls Title entities can call most non-Client-prefixed APIs (Inventory, Leaderboards, Data, etc.), not just Server-prefixed ones. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix API scope: Client=player-only, Server=title-only, non-prefixed=both Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Link PFEntity API table to reference docs 16 of 18 functions linked to their api-references pages. PFEntityGetTitleId/Size don't have reference pages yet. Added link to PFEntity members page. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add API reference links to new doc pages Link first-use function references to api-references pages in: - http-config.md (PFInitialize, PFServicesInitialize) - lifecycle.md (PFMemSetFunctions, PFInitialize, PFServicesInitialize, PFServiceConfig*, PFServicesUninitializeAsync, PFUninitializeAsync) - tracing.md (PFTraceEnableTraceToFile) - eventpipeline.md (PFEventPipelineDuplicateHandle, CloseHandle, UpdateConfiguration, Config struct) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add new pages to TOC: lifecycle, entity-handles, http-config, errors Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Replace GDK with Windows in new doc pages Unified Windows binaries now cover all Windows game stores. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify PFInitialize is required when using custom memory hooks PFServicesInitialize can call PFInitialize internally, but that bypasses PFMemSetFunctions. Both lifecycle.md and memory.md now explain this explicitly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add API reference links across all C SDK docs Consistent first-use linking of PF* functions to their reference pages in memory.md, async.md, relogin.md, server.md, lifecycle.md, entity-handles.md, eventpipeline.md, and eventpipeline-tutorial.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Acrolinx issues in memory.md - Present perfect → simple present (haven't been applied → aren't applied) - Future tense → simple present (will call → call) - Remove spaces around em dash (— but → —but) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- playfab-docs/sdks/c/async.md | 4 +- playfab-docs/sdks/c/entity-handles.md | 330 ++++++++++++++++++ .../event-pipeline/eventpipeline-tutorial.md | 14 +- .../sdks/c/event-pipeline/eventpipeline.md | 48 ++- playfab-docs/sdks/c/http-config.md | 137 ++++++++ playfab-docs/sdks/c/lifecycle.md | 267 ++++++++++++++ playfab-docs/sdks/c/memory.md | 16 +- playfab-docs/sdks/c/relogin.md | 6 +- playfab-docs/sdks/c/server.md | 2 +- playfab-docs/sdks/c/tracing.md | 10 + playfab-docs/sdks/toc.yml | 8 + 11 files changed, 814 insertions(+), 28 deletions(-) create mode 100644 playfab-docs/sdks/c/entity-handles.md create mode 100644 playfab-docs/sdks/c/http-config.md create mode 100644 playfab-docs/sdks/c/lifecycle.md diff --git a/playfab-docs/sdks/c/async.md b/playfab-docs/sdks/c/async.md index 187feff4c..2209100f0 100644 --- a/playfab-docs/sdks/c/async.md +++ b/playfab-docs/sdks/c/async.md @@ -16,7 +16,7 @@ An asynchronous API is an API that returns quickly but starts an asynchronous ta Traditionally, games have had little control over which thread executes the asynchronous task and which thread returns the results when using a completion callback. Some games are designed so that a section of the heap is only touched by a single thread to avoid any need for thread synchronization. If the completion callback isn't called from a thread the game controls, updating shared state with the result of an asynchronous task requires thread synchronization. -The PlayFab Services SDK exposes an asynchronous C API that gives developers direct thread control when making an asynchronous API call, such as **PFAuthenticationLoginWithCustomIDAsync**, **PFDataGetFilesAsync**, or **PFProfilesGetProfileAsync**. +The PlayFab Services SDK exposes an asynchronous C API that gives developers direct thread control when making an asynchronous API call, such as [**PFAuthenticationLoginWithCustomIDAsync**](../../api-references/c/pfauthentication/functions/pfauthenticationloginwithcustomidasync.md), [**PFDataGetFilesAsync**](../../api-references/c/pfdata/functions/pfdatagetfilesasync.md), or [**PFProfilesGetProfileAsync**](../../api-references/c/pfprofiles/functions/pfprofilesgetprofileasync.md). Here's a basic example calling **PFProfilesGetProfileAsync**: @@ -104,7 +104,7 @@ Once the asynchronous task is complete, you can get the results. To get the result, most asynchronous API functions have a corresponding Result function to receive the result of the asynchronous call. -In our example code, **PFProfilesGetProfileAsync** has a corresponding **PFProfilesGetProfileGetResult** function. You can use this function to retrieve the result of the function and act accordingly. +In our example code, **PFProfilesGetProfileAsync** has a corresponding [**PFProfilesGetProfileGetResult**](../../api-references/c/pfprofiles/functions/pfprofilesgetprofilegetresult.md) function. You can use this function to retrieve the result of the function and act accordingly. For full details on retrieving results, see the documentation of each asynchronous API function. diff --git a/playfab-docs/sdks/c/entity-handles.md b/playfab-docs/sdks/c/entity-handles.md new file mode 100644 index 000000000..e3d89f467 --- /dev/null +++ b/playfab-docs/sdks/c/entity-handles.md @@ -0,0 +1,330 @@ +--- +title: Entity Handles +author: amccalib +description: Managing entity handles and token lifecycle in the PlayFab Services SDK +ms.author: andmcc +ms.date: 02/14/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, c++, windows, xbox, gdk, entity, handles, tokens +ms.localizationpriority: medium +--- + +# Entity Handles + +A __PFEntityHandle__ is your primary credential for making PlayFab service calls. It represents an authenticated entity—either a player (title_player_account) or a title—and holds the entity token the SDK needs to authorize requests. Every login or authentication call returns a __PFEntityHandle__, and every service call requires one. + +## Getting an entity handle + +You don't create entity handles directly. Instead, you get one as an output of a successful login or authentication call. + +**Player login (Windows example):** + +```cpp +PFAuthenticationLoginWithXUserRequest request{}; +request.createAccount = true; +request.user = userHandle; // XUserHandle from XUserAddAsync + +XAsyncBlock async{}; +HRESULT hr = PFAuthenticationLoginWithXUserAsync(serviceConfigHandle, &request, &async); +hr = XAsyncGetStatus(&async, true); + +PFEntityHandle entityHandle{ nullptr }; +size_t bufferSize{}; +hr = PFAuthenticationLoginWithXUserGetResultSize(&async, &bufferSize); + +std::vector loginResultBuffer(bufferSize); +PFAuthenticationLoginResult const* loginResult{}; +hr = PFAuthenticationLoginWithXUserGetResult( + &async, &entityHandle, + loginResultBuffer.size(), loginResultBuffer.data(), + &loginResult, nullptr); +``` + +**Title entity (server):** + +Title entities authenticate with a secret key instead of a user credential. The returned __PFEntityHandle__ works the same way, but it represents the title rather than a player. See [Accessing PlayFab with a title entity](server.md) for details. + +## Handle ownership and ref counting + +__PFEntityHandle__ is ref-counted. When you receive a handle from a login call, you own one reference. You can create additional references with [__PFEntityDuplicateHandle__](../../api-references/c/pfentity/functions/pfentityduplicatehandle.md) and release them with [__PFEntityCloseHandle__](../../api-references/c/pfentity/functions/pfentityclosehandle.md). The underlying entity object is destroyed only when the last reference is closed. + +**Rules:** + +- Every call to a login `GetResult` function or __PFEntityDuplicateHandle__ gives you a handle you must close. +- Closing a handle doesn't invalidate other handles to the same entity. +- Close all handles before calling [__PFServicesUninitializeAsync__](../../api-references/c/pfservices/functions/pfservicesuninitializeasync.md). + +```cpp +// Duplicate a handle for another component +PFEntityHandle secondHandle{ nullptr }; +HRESULT hr = PFEntityDuplicateHandle(entityHandle, &secondHandle); + +// Both handles are independently valid +// ... + +// Each owner closes their own handle +PFEntityCloseHandle(secondHandle); +PFEntityCloseHandle(entityHandle); +``` + +## Getting entity info + +### Entity key + +The entity key identifies the entity (its type and ID). Use the two-call pattern: get the size first, then get the data. + +```cpp +size_t size{}; +HRESULT hr = PFEntityGetEntityKeySize(entityHandle, &size); + +std::vector buffer(size); +PFEntityKey const* entityKey{}; +hr = PFEntityGetEntityKey(entityHandle, buffer.size(), buffer.data(), &entityKey, nullptr); + +// entityKey->type is "title_player_account" for players +// entityKey->id is the entity's unique ID +``` + +### Entity token + +The entity token authorizes service calls. The SDK manages tokens automatically, but you can retrieve the current one if needed. + +```cpp +XAsyncBlock async{}; +HRESULT hr = PFEntityGetEntityTokenAsync(entityHandle, &async); +hr = XAsyncGetStatus(&async, true); + +size_t size{}; +hr = PFEntityGetEntityTokenResultSize(&async, &size); + +std::vector buffer(size); +const PFEntityToken* entityToken{}; +hr = PFEntityGetEntityTokenResult(&async, buffer.size(), buffer.data(), &entityToken, nullptr); + +// entityToken->token is the token string +// entityToken->expiration is the optional expiration time (UTC) +``` + +### Checking entity type + +Use [__PFEntityIsTitlePlayer__](../../api-references/c/pfentity/functions/pfentityistitleplayer.md) as a quick check instead of inspecting the entity key type string: + +```cpp +bool isTitlePlayer{}; +HRESULT hr = PFEntityIsTitlePlayer(entityHandle, &isTitlePlayer); +``` + +## Player entities vs. title entities + +Both player and title entities use __PFEntityHandle__, but they differ in what they can do: + +| | Player entity | Title entity | +|---|---|---| +| **How you get it** | Login call (e.g., `PFAuthenticationLoginWithXUserAsync`) | `PFAuthenticationGetEntityWithSecretKeyAsync` | +| **Entity type** | `title_player_account` | `title` | +| [**PFEntityIsTitlePlayer**](../../api-references/c/pfentity/functions/pfentityistitleplayer.md) | Returns `true` | Returns `false` | +| [**PFEntityGetSecretKey**](../../api-references/c/pfentity/functions/pfentitygetsecretkey.md) | Fails with `E_PF_NOSECRETKEY` | Returns the secret key | +| **Available APIs** | Client-prefixed and non-prefixed APIs | Server-prefixed and non-prefixed APIs | + +Non-prefixed APIs (e.g., Inventory, Leaderboards, Data) can generally be called by both player and title entities unless otherwise noted in their documentation. Client-prefixed APIs are player-only, and Server-prefixed APIs are title-only. + +__PFEntityGetSecretKey__ retrieves the secret key associated with a title entity. It fails for player entities because they don't have one. + +```cpp +size_t keySize{}; +HRESULT hr = PFEntityGetSecretKeySize(entityHandle, &keySize); +if (SUCCEEDED(hr)) +{ + std::vector secretKey(keySize); + hr = PFEntityGetSecretKey(entityHandle, secretKey.size(), secretKey.data(), nullptr); +} +``` + +> [!NOTE] +> __PFEntityGetSecretKey__ is only available on Windows, Linux, and macOS platforms. + +## Token event handlers + +The SDK automatically refreshes entity tokens before they expire. You can register callbacks to observe these events. + +### Token expired + +If automatic refresh fails (for example, the original login credential is no longer valid), the SDK fires the token-expired event. Register a handler to provide a new credential and retry the login. + +```cpp +PFRegistrationToken registrationToken{}; +HRESULT hr = PFEntityRegisterTokenExpiredEventHandler( + nullptr, // XTaskQueueHandle, or nullptr for default + nullptr, // optional context + [](void* ctx, PFEntityKey const* entityKey) + { + // Re-authenticate the player with a fresh credential + // See relogin.md for a complete example + }, + ®istrationToken); +``` + +### Token refreshed + +Register a token-refreshed handler if you want to know when the SDK successfully refreshes a token in the background. This is informational—you don't need to take any action. + +```cpp +PFRegistrationToken registrationToken{}; +HRESULT hr = PFEntityRegisterTokenRefreshedEventHandler( + nullptr, // XTaskQueueHandle, or nullptr for default + nullptr, // optional context + [](void* ctx, PFEntityKey const* entityKey, const PFEntityToken* newToken) + { + // Log the refresh or update cached token references + }, + ®istrationToken); +``` + +### When to register and unregister + +- **Register** handlers early, right after SDK initialization and before login. This ensures you don't miss any events. +- **Unregister** handlers during shutdown, before you close entity handles. + +```cpp +PFEntityUnregisterTokenExpiredEventHandler(expiredRegistrationToken); +PFEntityUnregisterTokenRefreshedEventHandler(refreshedRegistrationToken); +``` + +For a complete walkthrough of token expiration handling and relogin, see [Handling Token Expiration](relogin.md). + +## Utility accessors + +You can retrieve the API endpoint and title ID from an entity handle. These come from the __PFServiceConfigHandle__ that was used during login. + +```cpp +// Get API endpoint +size_t endpointSize{}; +HRESULT hr = PFEntityGetAPIEndpointSize(entityHandle, &endpointSize); + +std::vector endpoint(endpointSize); +hr = PFEntityGetAPIEndpoint(entityHandle, endpoint.size(), endpoint.data(), nullptr); + +// Get title ID +size_t titleIdSize{}; +hr = PFEntityGetTitleIdSize(entityHandle, &titleIdSize); + +std::vector titleId(titleIdSize); +hr = PFEntityGetTitleId(entityHandle, titleId.size(), titleId.data(), nullptr); +``` + +## Complete example + +This example demonstrates creating, duplicating, querying, and closing entity handles: + +```cpp +#include +#include + +void EntityHandleExample(PFServiceConfigHandle serviceConfigHandle, XUserHandle userHandle) +{ + // + // Log in and get an entity handle + // + PFAuthenticationLoginWithXUserRequest request{}; + request.createAccount = true; + request.user = userHandle; + + XAsyncBlock asyncLogin{}; + HRESULT hr = PFAuthenticationLoginWithXUserAsync(serviceConfigHandle, &request, &asyncLogin); + hr = XAsyncGetStatus(&asyncLogin, true); + + PFEntityHandle entityHandle{ nullptr }; + size_t resultSize{}; + hr = PFAuthenticationLoginWithXUserGetResultSize(&asyncLogin, &resultSize); + + std::vector loginBuffer(resultSize); + PFAuthenticationLoginResult const* loginResult{}; + hr = PFAuthenticationLoginWithXUserGetResult( + &asyncLogin, &entityHandle, + loginBuffer.size(), loginBuffer.data(), + &loginResult, nullptr); + + // + // Register token event handlers + // + PFRegistrationToken expiredToken{}; + hr = PFEntityRegisterTokenExpiredEventHandler(nullptr, nullptr, + [](void* ctx, PFEntityKey const* entityKey) + { + // Handle re-authentication + }, &expiredToken); + + PFRegistrationToken refreshedToken{}; + hr = PFEntityRegisterTokenRefreshedEventHandler(nullptr, nullptr, + [](void* ctx, PFEntityKey const* entityKey, const PFEntityToken* newToken) + { + // Log token refresh + }, &refreshedToken); + + // + // Duplicate the handle for a subsystem + // + PFEntityHandle subsystemHandle{ nullptr }; + hr = PFEntityDuplicateHandle(entityHandle, &subsystemHandle); + + // + // Query entity info + // + bool isTitlePlayer{}; + hr = PFEntityIsTitlePlayer(entityHandle, &isTitlePlayer); + + size_t keySize{}; + hr = PFEntityGetEntityKeySize(entityHandle, &keySize); + + std::vector keyBuffer(keySize); + PFEntityKey const* entityKey{}; + hr = PFEntityGetEntityKey(entityHandle, keyBuffer.size(), keyBuffer.data(), &entityKey, nullptr); + + // + // ... make service calls with entityHandle or subsystemHandle ... + // + + // + // Cleanup: unregister handlers, then close all handles + // + PFEntityUnregisterTokenExpiredEventHandler(expiredToken); + PFEntityUnregisterTokenRefreshedEventHandler(refreshedToken); + + PFEntityCloseHandle(subsystemHandle); + PFEntityCloseHandle(entityHandle); +} +``` + +## API reference + +| Function | Description | +|---|---| +| [PFEntityDuplicateHandle](../../api-references/c/pfentity/functions/pfentityduplicatehandle.md) | Duplicates a handle, incrementing the ref count. Both handles must be closed independently. | +| [PFEntityCloseHandle](../../api-references/c/pfentity/functions/pfentityclosehandle.md) | Closes a handle, decrementing the ref count. The entity is destroyed when the last handle is closed. | +| [PFEntityGetEntityKeySize](../../api-references/c/pfentity/functions/pfentitygetentitykeysize.md) | Gets the buffer size needed to store the entity key. | +| [PFEntityGetEntityKey](../../api-references/c/pfentity/functions/pfentitygetentitykey.md) | Gets the entity key (type and ID) for the entity. | +| [PFEntityGetEntityTokenAsync](../../api-references/c/pfentity/functions/pfentitygetentitytokenasync.md) | Retrieves the cached entity token asynchronously. | +| [PFEntityGetEntityTokenResultSize](../../api-references/c/pfentity/functions/pfentitygetentitytokenresultsize.md) | Gets the buffer size needed for the entity token result. | +| [PFEntityGetEntityTokenResult](../../api-references/c/pfentity/functions/pfentitygetentitytokenresult.md) | Gets the entity token from a completed PFEntityGetEntityTokenAsync call. | +| [PFEntityIsTitlePlayer](../../api-references/c/pfentity/functions/pfentityistitleplayer.md) | Returns whether the entity is a title_player_account. | +| [PFEntityGetSecretKeySize](../../api-references/c/pfentity/functions/pfentitygetsecretkeysize.md) | Gets the buffer size needed for the secret key. Fails if the entity isn't a title entity. | +| [PFEntityGetSecretKey](../../api-references/c/pfentity/functions/pfentitygetsecretkey.md) | Gets the secret key for a title entity. Only available on Windows, Linux, and macOS. | +| [PFEntityGetAPIEndpointSize](../../api-references/c/pfentity/functions/pfentitygetapiendpointsize.md) | Gets the buffer size needed for the API endpoint string. | +| [PFEntityGetAPIEndpoint](../../api-references/c/pfentity/functions/pfentitygetapiendpoint.md) | Gets the API endpoint from the entity's associated service config. | +| __PFEntityGetTitleIdSize__ | Gets the buffer size needed for the title ID string. | +| __PFEntityGetTitleId__ | Gets the title ID from the entity's associated service config. | +| [PFEntityRegisterTokenExpiredEventHandler](../../api-references/c/pfentity/functions/pfentityregistertokenexpiredeventhandler.md) | Registers a callback for when automatic token refresh fails. | +| [PFEntityUnregisterTokenExpiredEventHandler](../../api-references/c/pfentity/functions/pfentityunregistertokenexpiredeventhandler.md) | Unregisters a token-expired callback. | +| [PFEntityRegisterTokenRefreshedEventHandler](../../api-references/c/pfentity/functions/pfentityregistertokenrefreshedeventhandler.md) | Registers a callback for when the SDK successfully refreshes a token. | +| [PFEntityUnregisterTokenRefreshedEventHandler](../../api-references/c/pfentity/functions/pfentityunregistertokenrefreshedeventhandler.md) | Unregisters a token-refreshed callback. | + +For the complete API reference, see [PFEntity members](../../api-references/c/pfentity/pfentity_members.md). + +## See also + +- [Handling Token Expiration](relogin.md) +- [Accessing PlayFab with a title entity](server.md) +- [SDK Lifecycle](lifecycle.md) +- [Quickstart: Windows](quickstart-gdk.md) +- [Quickstart: Win32](quickstart-win32.md) diff --git a/playfab-docs/sdks/c/event-pipeline/eventpipeline-tutorial.md b/playfab-docs/sdks/c/event-pipeline/eventpipeline-tutorial.md index 5de18daa4..dacb359b0 100644 --- a/playfab-docs/sdks/c/event-pipeline/eventpipeline-tutorial.md +++ b/playfab-docs/sdks/c/event-pipeline/eventpipeline-tutorial.md @@ -16,7 +16,7 @@ This document is a quick step-by-step tutorial on how to use the Event Pipeline ## Step 1 - Initialize PlayFab Services SDK -The first step is to initialize PF Service SDK using **PFServicesInitialize** and **PFServiceConfigCreateHandle** APIs. +The first step is to initialize PF Service SDK using [**PFServicesInitialize**](../../../api-references/c/pfservices/functions/pfservicesinitialize.md) and [**PFServiceConfigCreateHandle**](../../../api-references/c/pfserviceconfig/functions/pfserviceconfigcreatehandle.md) APIs. The **PFServiceConfigCreateHandle** API receives a connection string and a title ID that can be obtained from your title on PlayFab Game Manager. @@ -36,7 +36,7 @@ PFServiceConfigCreateHandle( ## Step 2 - Create Telemetry Event Pipeline -Next, let's create a Telemetry Event Pipeline with a Telemetry Key using the **PFEventPipelineCreateTelemetryPipelineHandleWithKey** API. Telemetry Keys are created and managed through PlayFab Game Manager. +Next, let's create a Telemetry Event Pipeline with a Telemetry Key using the [**PFEventPipelineCreateTelemetryPipelineHandleWithKey**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelinecreatetelemetrypipelinehandlewithkey.md) API. Telemetry Keys are created and managed through PlayFab Game Manager. When creating the PFEventPipelineTelemetryKeyConfig struct, we're passing the actual telemetry key and the service config handle we got during SDK initialization. @@ -76,7 +76,7 @@ Also, since we're sending maxWaitTimeInSeconds and pollDelayInMs as null pointer We're also specifying a "Medium" compression level, setting this property compresses the body payloads and helps to optimize network resources utilization. -Then we proceed to call **PFEventPipelineUpdateConfiguration** passing the **PFEventPipelineHandle** that we got from previous step and the **PFEventPipelineConfig** struct. +Then we proceed to call [**PFEventPipelineUpdateConfiguration**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineupdateconfiguration.md) passing the **PFEventPipelineHandle** that we got from previous step and the **PFEventPipelineConfig** struct. ```cpp uint32_t maxEvents = 10; @@ -104,7 +104,7 @@ if (FAILED(hr)) ## Step 4 - Emit event -On this step, we proceed to emit just 1 event with name "TelemetryKeyEvent" through **PFEventPipelineEmitEvent** API. +On this step, we proceed to emit just 1 event with name "TelemetryKeyEvent" through [**PFEventPipelineEmitEvent**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineemitevent.md) API. This event isn't linked to any entities since we haven't provided entity authentication so far. @@ -134,7 +134,7 @@ if (FAILED(hr)) Here, we want to get an Entity that we can use to start linking with our events. -For this tutorial, we're calling **PFAuthenticationReLoginWithXUserAsync** API to get a valid **PFEntityHandle**. +For this tutorial, we're calling [**PFAuthenticationReLoginWithXUserAsync**](../../../api-references/c/pfauthentication/functions/pfauthenticationreloginwithxuserasync.md) API to get a valid **PFEntityHandle**. > [!NOTE] > The userHandle object passed as part of the **PFAuthenticationLoginWithXUserRequest** is of XUserHandle type. The steps on how to get a valid XUserHandle are out of scope for this tutorial. For more information on this topic, see [XUserAddAsync](/gaming/gdk/_content/gc/reference/system/xuser/functions/xuseraddasync) documentation. @@ -167,7 +167,7 @@ if (FAILED(hr)) ## Step 6 - Add Entity to Pipeline -Since we already got a valid Entity, we can call **PFEventPipelineAddUploadingEntity** and pass the Event Pipeline handle and the entity handle from the previous step. This action allows the pipeline to switch to use entity authentication. +Since we already got a valid Entity, we can call [**PFEventPipelineAddUploadingEntity**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineadduploadingentity.md) and pass the Event Pipeline handle and the entity handle from the previous step. This action allows the pipeline to switch to use entity authentication. ```cpp HRESULT hr = PFEventPipelineAddUploadingEntity( @@ -215,7 +215,7 @@ if (FAILED(hr)) ## Step 8 - Close Event Pipeline handle -Lastly, when we're done uploading events, the only thing we need to do is to call **PFEventPipelineCloseHandle** passing our pipeline handle. +Lastly, when we're done uploading events, the only thing we need to do is to call [**PFEventPipelineCloseHandle**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineclosehandle.md) passing our pipeline handle. ```cpp PFEventPipelineCloseHandle(handle); diff --git a/playfab-docs/sdks/c/event-pipeline/eventpipeline.md b/playfab-docs/sdks/c/event-pipeline/eventpipeline.md index 3a18a3ee0..1840766af 100644 --- a/playfab-docs/sdks/c/event-pipeline/eventpipeline.md +++ b/playfab-docs/sdks/c/event-pipeline/eventpipeline.md @@ -68,7 +68,7 @@ If Telemetry Key auth is used, a **PFEventPipelineTelemetryKeyConfig** struct is 1. A Telemetry Key that consists of a string that is created and managed via PlayFab Game Manager. -2. A **PFServiceConfigHandle** that lets the SDK know which is the right service configuration that should be used for uploading the events. The service config handle is created during SDK Initialization by calling **PFServiceConfigCreateHandle**. +2. A **PFServiceConfigHandle** that lets the SDK know which is the right service configuration that should be used for uploading the events. The service config handle is created during SDK Initialization by calling [**PFServiceConfigCreateHandle**](../../../api-references/c/pfserviceconfig/functions/pfserviceconfigcreatehandle.md). If the developer wants to use a Telemetry Key it's important to provide it at pipeline creation, since there's no way to add a Telemetry Key after the pipeline has been instantiated. @@ -87,7 +87,18 @@ The configurable properties are: - **retryOnDisconnect**: The event pipeline will retry sending events that failed due to lost connection. Only available for Telemetry Event Pipeline. - **bufferSize**: The limit of the amount of events in the pipeline's buffer. -In the case where **PFEventPipelineConfig** has only some properties specified, the ones being empty are overwritten and use the default values. +### Default values + +| Property | Telemetry Pipeline | PlayStream Pipeline | +|---|---|---| +| **maxEventsPerBatch** | 5 | 5 | +| **maxWaitTimeInSeconds** | 3 | 3 | +| **pollDelayInMs** | 3000 | 10 | +| **compressionLevel** | None (disabled) | None (disabled) | +| **retryOnDisconnect** | true | N/A | +| **bufferSize** | 1024 | 1024 | + +In the case where [**PFEventPipelineConfig**](../../../api-references/c/pfeventpipeline/structs/pfeventpipelineconfig.md) has only some properties specified, the ones being empty are overwritten and use the default values. For an example of how any of these properties can be updated for the event pipeline see _[Update Pipeline Configuration](#update-pipeline-configuration)_. @@ -95,7 +106,7 @@ For an example of how any of these properties can be updated for the event pipel The Event Pipeline provides an option of compressing body payloads using GZIP Compression standard. -The desired compression level can be specified inside the **PFEventPipelineConfig** struct that is part of the **PFEventPipelineUpdateConfiguration** API parameters. +The desired compression level can be specified inside the **PFEventPipelineConfig** struct that is part of the [**PFEventPipelineUpdateConfiguration**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineupdateconfiguration.md) API parameters. A lower compression level achieves less compression but has the highest speed and a higher compression level achieves better compression rates but has the slowest compression speed. The difference in compression rates is all dependent on the type of data being sent. Depending on the size and randomness of the data, compression rates can be the same even on different levels. @@ -113,9 +124,9 @@ However, if the game developer wants a "fire and forget" experience, can omit pr The event handlers that can be provided are as follows: -- **PFEventPipelineBatchUploadSucceededEventHandler**: As the name suggests, it receives all the events that are successfully uploaded to PlayFab. +- [**PFEventPipelineBatchUploadSucceededEventHandler**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelinebatchuploadsucceededeventhandler.md): As the name suggests, it receives all the events that are successfully uploaded to PlayFab. -- **PFEventPipelineBatchUploadFailedEventHandler**: It will receive all the failed events after going through the pipeline retry logic. +- [**PFEventPipelineBatchUploadFailedEventHandler**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelinebatchuploadfailedeventhandler.md): It will receive all the failed events after going through the pipeline retry logic. ### Pipeline creation examples @@ -123,7 +134,7 @@ Below you can find different examples on how to instantiate an event pipeline ba 1. **Telemetry Event Pipeline creation with Entity auth** - If the developer wants to send Telemetry Events and doesn't have the need of using Telemetry Key auth, the **PFEventPipelineCreateTelemetryPipelineHandleWithEntity** API serves for this purpose as seen in the next example: + If the developer wants to send Telemetry Events and doesn't have the need of using Telemetry Key auth, the [**PFEventPipelineCreateTelemetryPipelineHandleWithEntity**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelinecreatetelemetrypipelinehandlewithentity.md) API serves for this purpose as seen in the next example: ```cpp void EventPipelineCreation(PFEntityHandle entityHandle, XTaskQueueHandle taskQueueHandle) @@ -253,7 +264,7 @@ As seen in the example, ***OnBatchUploadedHandler*** and ***OnBatchUploadFailedH ### Emitting events -Emitting events is a straightforward operation once the event pipeline is already created. The game developer should call **PFEventPipelineEmitEvent** API that receives the existing event pipeline handle and the event they want to send. +Emitting events is a straightforward operation once the event pipeline is already created. The game developer should call [**PFEventPipelineEmitEvent**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineemitevent.md) API that receives the existing event pipeline handle and the event they want to send. ```cpp void EmitEvent(PFEventPipelineHandle handle) @@ -321,7 +332,7 @@ Make sure to set an adequate size of a buffer for your needs. If a pipeline was created using only a Telemetry Key configuration, there's a way to switch to Entity authentication or if you want to update your pipeline to use a different Entity. -By using the **PFEventPipelineAddUploadingEntity**, it's possible to attach an entity to a running pipeline without the need of reinitialize it. It also replaces the existing entity, if any. +By using the [**PFEventPipelineAddUploadingEntity**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineadduploadingentity.md), it's possible to attach an entity to a running pipeline without the need of reinitialize it. It also replaces the existing entity, if any. Example: @@ -377,7 +388,7 @@ After this call, the pipeline will start logging any subsequent events linked to ### Switching to Telemetry Key auth -Expanding on the previous scenario, if the developer wants to go back to Telemetry Auth and detach the event logging from the entity they can call **PFEventPipelineRemoveUploadingEntity** and pass the event pipeline handle like this: +Expanding on the previous scenario, if the developer wants to go back to Telemetry Auth and detach the event logging from the entity they can call [**PFEventPipelineRemoveUploadingEntity**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineremoveuploadingentity.md) and pass the event pipeline handle like this: ```cpp void EventPipelineRemoveEntity(PFEventPipelineHandle handle) @@ -398,7 +409,7 @@ This call removes the entity and effectively switches back to Telemetry Key auth ### **Update Pipeline configuration** -Pipelines can be easily updated using the **PFEventPipelineUpdateConfiguration** API, which receives the existing event pipeline handle and a new configuration struct as follows: +Pipelines can be easily updated using the [**PFEventPipelineUpdateConfiguration**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineupdateconfiguration.md) API, which receives the existing event pipeline handle and a new configuration struct as follows: ```cpp void EventPipelineUpdateConfiguration(PFEventPipelineHandle handle) @@ -441,6 +452,23 @@ In case a Telemetry key is deactivated or if an invalid key is provided at pipel In the eventual case where the customer reactivates the key, the pipeline won't realize about that and will keep sending failures back through the failed event handler. It's worth mentioning that this behavior is session-based, which means that if the title is restarted, a new pipeline is created and will be able to upload events again. +## Pipeline handle lifecycle + +Like other PlayFab handles, event pipeline handles use a duplicate/close pattern: + +- [**PFEventPipelineCloseHandle**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineclosehandle.md): Closes a pipeline handle. When the last handle to a pipeline is closed, the pipeline is destroyed and any remaining buffered events are flushed. +- [**PFEventPipelineDuplicateHandle**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineduplicatehandle.md): Duplicates a pipeline handle. Both the original and duplicated handle must be closed independently with [**PFEventPipelineCloseHandle**](../../../api-references/c/pfeventpipeline/functions/pfeventpipelineclosehandle.md). + +```cpp +// Duplicate a handle for use in another component +PFEventPipelineHandle duplicatedHandle; +HRESULT hr = PFEventPipelineDuplicateHandle(originalHandle, &duplicatedHandle); + +// When done, close both handles independently +PFEventPipelineCloseHandle(duplicatedHandle); +PFEventPipelineCloseHandle(originalHandle); +``` + ## See also - [Event pipeline tutorial](eventpipeline-tutorial.md) diff --git a/playfab-docs/sdks/c/http-config.md b/playfab-docs/sdks/c/http-config.md new file mode 100644 index 000000000..3243f8e80 --- /dev/null +++ b/playfab-docs/sdks/c/http-config.md @@ -0,0 +1,137 @@ +--- +title: HTTP Configuration +author: amccalib +description: Configuring HTTP retry and compression settings in the PlayFab Services SDK +ms.author: andmcc +ms.date: 02/14/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, c++, windows, xbox, gdk, http, retry, compression +ms.localizationpriority: medium +--- + +# HTTP Configuration + +The PlayFab Services SDK provides functions to configure how HTTP requests are made, including automatic retry behavior and response compression. These settings are global and apply to all PlayFab API calls made by the SDK. + +Configure HTTP settings after calling [**PFInitialize**](../../api-references/c/pfcore/functions/pfinitialize.md) and [**PFServicesInitialize**](../../api-references/c/pfservices/functions/pfservicesinitialize.md), but before making any API calls. + +## Retry settings + +The **PFHttpRetrySettings** struct controls how the SDK handles transient HTTP failures, such as throttling errors (HTTP 429). By default, the SDK automatically retries these failures with backoff. + +| Field | Type | Default | Description | +|---|---|---|---| +| `allowRetry` | `bool` | `true` | Controls whether the SDK automatically retries select errors. Some errors are never retried and are always returned directly. | +| `minimumRetryDelayInSeconds` | `uint32_t` | 2 | The minimum number of seconds to wait before retrying a failed request. Can't be set below 2 seconds. | +| `timeoutWindowInSeconds` | `uint32_t` | 20 | The maximum number of seconds the SDK attempts retries before returning the error to the caller. | + +For more information on which errors the SDK retries automatically, see [Handling PlayFab Errors](errors.md). + +### Set retry settings + +Call **PFSetHttpRetrySettings** to customize the retry behavior. For example, to increase the retry window for calls that can tolerate longer waits: + +```cpp +PFHttpRetrySettings retrySettings{}; +retrySettings.allowRetry = true; +retrySettings.minimumRetryDelayInSeconds = 4; +retrySettings.timeoutWindowInSeconds = 60; + +HRESULT hr = PFSetHttpRetrySettings(&retrySettings); +if (FAILED(hr)) +{ + // Handle error +} +``` + +### Get retry settings + +Call **PFGetHttpRetrySettings** to retrieve the current retry configuration: + +```cpp +PFHttpRetrySettings currentSettings{}; +HRESULT hr = PFGetHttpRetrySettings(¤tSettings); +if (SUCCEEDED(hr)) +{ + printf("Retry enabled: %s\n", currentSettings.allowRetry ? "true" : "false"); + printf("Min delay: %u seconds\n", currentSettings.minimumRetryDelayInSeconds); + printf("Timeout window: %u seconds\n", currentSettings.timeoutWindowInSeconds); +} +``` + +### Disable automatic retries + +If you want to handle all retry logic yourself, disable automatic retries: + +```cpp +PFHttpRetrySettings retrySettings{}; +retrySettings.allowRetry = false; +retrySettings.minimumRetryDelayInSeconds = 2; +retrySettings.timeoutWindowInSeconds = 20; + +HRESULT hr = PFSetHttpRetrySettings(&retrySettings); +``` + +## HTTP settings + +The **PFHttpSettings** struct controls general HTTP behavior for all SDK requests. + +| Field | Type | Default | Description | +|---|---|---|---| +| `requestResponseCompression` | `bool` | `false` | When enabled, the SDK requests that API responses be gzip-compressed by setting the `Accept-Encoding` header to `application/gzip`. | + +### Enable response compression + +Enabling response compression can reduce bandwidth usage, which is useful for calls that return large payloads. Call **PFSetHttpSettings** to enable it: + +```cpp +PFHttpSettings httpSettings{}; +httpSettings.requestResponseCompression = true; + +HRESULT hr = PFSetHttpSettings(&httpSettings); +if (FAILED(hr)) +{ + // Handle error +} +``` + +> [!NOTE] +> To decompress a compressed response, **HCHttpCallResponseSetGzipCompressed** must be called before calling **HCHttpCallPerformAsync**. + +### Get HTTP settings + +Call **PFGetHttpSettings** to retrieve the current HTTP configuration: + +```cpp +PFHttpSettings currentSettings{}; +HRESULT hr = PFGetHttpSettings(¤tSettings); +if (SUCCEEDED(hr)) +{ + printf("Response compression: %s\n", currentSettings.requestResponseCompression ? "enabled" : "disabled"); +} +``` + +## Typical initialization pattern + +The following example shows where HTTP configuration fits into the overall SDK initialization flow: + +```cpp +// 1. Initialize the SDK +HRESULT hr = PFInitialize(nullptr); +hr = PFServicesInitialize(nullptr); + +// 2. Configure HTTP settings before making any API calls +PFHttpRetrySettings retrySettings{}; +retrySettings.allowRetry = true; +retrySettings.minimumRetryDelayInSeconds = 2; +retrySettings.timeoutWindowInSeconds = 30; +PFSetHttpRetrySettings(&retrySettings); + +PFHttpSettings httpSettings{}; +httpSettings.requestResponseCompression = true; +PFSetHttpSettings(&httpSettings); + +// 3. Create service config and begin making API calls +// ... +``` diff --git a/playfab-docs/sdks/c/lifecycle.md b/playfab-docs/sdks/c/lifecycle.md new file mode 100644 index 000000000..c810b14ac --- /dev/null +++ b/playfab-docs/sdks/c/lifecycle.md @@ -0,0 +1,267 @@ +--- +title: SDK Lifecycle +author: amccalib +description: Initialization, configuration, and shutdown of the PlayFab Services SDK +ms.author: andmcc +ms.date: 02/14/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, c++, windows, xbox, gdk, initialization, shutdown, lifecycle +ms.localizationpriority: medium +--- + +# SDK Lifecycle + +This page covers the complete startup and shutdown sequence for the PlayFab Services SDK. Every title follows the same high-level pattern: configure optional hooks, initialize Core, create a service configuration, initialize Services, do work, then shut down in reverse order. + +## Initialization sequence + +Initialization has four steps. The first is optional; the remaining three are required. + +``` +PFMemSetFunctions (optional) → PFInitialize → PFServiceConfigCreateHandle → PFServicesInitialize +``` + +### Step 1: Set custom memory hooks (optional) + +If your title uses a custom memory allocator, call [**PFMemSetFunctions**](../../api-references/c/pfplatform/functions/pfmemsetfunctions.md) before any other PlayFab API. This routes all SDK memory allocations through your own `alloc` and `free` callbacks. + +```cpp +PFMemoryHooks hooks{}; +hooks.alloc = MyAllocFunction; +hooks.free = MyFreeFunction; +HRESULT hr = PFMemSetFunctions(&hooks); +``` + +> [!IMPORTANT] +> [__PFMemSetFunctions__](../../api-references/c/pfplatform/functions/pfmemsetfunctions.md) must be called before [**PFInitialize**](../../api-references/c/pfcore/functions/pfinitialize.md). It can't be called again after hooks have been set. + +If you don't need custom memory management, skip this step. The SDK uses default allocation routines. + +### Step 2: Initialize PlayFab Core + +[__PFInitialize__](../../api-references/c/pfcore/functions/pfinitialize.md) sets up the SDK's global state, including the HTTP layer and background task queue. The exact signature varies by platform. + +#### Windows, Linux, iOS, and macOS + +```cpp +HRESULT hr = PFInitialize(nullptr); // Uses a default threadpool queue +``` + +Pass an __XTaskQueueHandle__ if you want to control which queue handles background work. Pass `nullptr` to use the default threadpool queue. + +#### Android + +On Android, you must also provide the Java VM and application context so the SDK can initialize libHttpClient: + +```cpp +HRESULT hr = PFInitialize(nullptr, javaVm, applicationContext); +``` + +> [!NOTE] +> If you don't call __PFInitialize__ explicitly, [**PFServicesInitialize**](../../api-references/c/pfservices/functions/pfservicesinitialize.md) calls it internally with default parameters. This is fine for most titles. However, if you're using custom memory hooks via __PFMemSetFunctions__, you **must** call __PFInitialize__ yourself — otherwise [__PFServicesInitialize__](../../api-references/c/pfservices/functions/pfservicesinitialize.md) initializes Core before your memory hooks take effect, and the SDK uses default allocation routines instead. + +### Step 3: Create a service configuration + +[**PFServiceConfigCreateHandle**](../../api-references/c/pfserviceconfig/functions/pfserviceconfigcreatehandle.md) creates a handle that tells the SDK which PlayFab title and endpoint to target. You'll find both values in [Game Manager](https://developer.playfab.com). + +```cpp +PFServiceConfigHandle serviceConfigHandle{ nullptr }; +HRESULT hr = PFServiceConfigCreateHandle( + "https://ABCDEF.playfabapi.com", // API endpoint from Game Manager + "ABCDEF", // Title ID from Game Manager + &serviceConfigHandle); +``` + +The returned __PFServiceConfigHandle__ is required for all subsequent login calls. + +### Step 4: Initialize PlayFab Services + +__PFServicesInitialize__ sets up the Services layer (Inventory, Leaderboards, Friends, and so on) on top of Core. + +#### Windows, Linux, iOS, and macOS + +```cpp +HRESULT hr = PFServicesInitialize(nullptr); +``` + +The parameter is reserved for future use; pass `nullptr`. + +#### Android + +On Android, pass an __HCInitArgs__ struct containing the Java VM and application context: + +```cpp +HRESULT hr = PFServicesInitialize(nullptr, initArgs); +``` + +After this call succeeds, the SDK is ready. You can log in players and make service calls. + +## PFServiceConfigHandle lifecycle + +A __PFServiceConfigHandle__ is a ref-counted handle. The SDK manages its internal lifetime through reference counting, but you're responsible for closing every handle you own. + +| Function | Description | +|---|---| +| [**PFServiceConfigCreateHandle**](../../api-references/c/pfserviceconfig/functions/pfserviceconfigcreatehandle.md) | Creates a new handle. The initial ref count is 1. | +| [**PFServiceConfigDuplicateHandle**](../../api-references/c/pfserviceconfig/functions/pfserviceconfigduplicatehandle.md) | Increments the ref count and returns a second handle. Both handles must be closed independently. | +| [**PFServiceConfigCloseHandle**](../../api-references/c/pfserviceconfig/functions/pfserviceconfigclosehandle.md) | Decrements the ref count. When it reaches 0, the config is destroyed. | +| [**PFServiceConfigGetAPIEndpoint**](../../api-references/c/pfserviceconfig/functions/pfserviceconfiggetapiendpoint.md) | Retrieves the API endpoint string. Call [**PFServiceConfigGetAPIEndpointSize**](../../api-references/c/pfserviceconfig/functions/pfserviceconfiggetapiendpointsize.md) first to determine the buffer size. | +| [**PFServiceConfigGetTitleId**](../../api-references/c/pfserviceconfig/functions/pfserviceconfiggettitleid.md) | Retrieves the title ID string. Call [**PFServiceConfigGetTitleIdSize**](../../api-references/c/pfserviceconfig/functions/pfserviceconfiggettitleidsize.md) first to determine the buffer size. | + +### Duplicating a handle + +Use [__PFServiceConfigDuplicateHandle__](../../api-references/c/pfserviceconfig/functions/pfserviceconfigduplicatehandle.md) when you need to share a service config across components that manage their own lifetimes: + +```cpp +PFServiceConfigHandle duplicatedHandle{ nullptr }; +HRESULT hr = PFServiceConfigDuplicateHandle(serviceConfigHandle, &duplicatedHandle); + +// Both handles are now valid and must be closed separately +PFServiceConfigCloseHandle(duplicatedHandle); +PFServiceConfigCloseHandle(serviceConfigHandle); +``` + +## Shutdown sequence + +Shutdown is the reverse of initialization. You must uninitialize Services before Core, and both calls are asynchronous. + +``` +Close handles → PFServicesUninitializeAsync → PFUninitializeAsync +``` + +### Step 1: Close all open handles + +Before tearing down the SDK, close every __PFEntityHandle__ and __PFServiceConfigHandle__ you own: + +```cpp +PFEntityCloseHandle(entityHandle); +entityHandle = nullptr; + +PFServiceConfigCloseHandle(serviceConfigHandle); +serviceConfigHandle = nullptr; +``` + +### Step 2: Uninitialize Services + +[**PFServicesUninitializeAsync**](../../api-references/c/pfservices/functions/pfservicesuninitializeasync.md) tears down the Services layer. Wait for it to complete before proceeding. + +```cpp +XAsyncBlock asyncServices{}; +HRESULT hr = PFServicesUninitializeAsync(&asyncServices); +hr = XAsyncGetStatus(&asyncServices, true); // Blocking wait +``` + +### Step 3: Uninitialize Core + +After Services cleanup finishes, call [**PFUninitializeAsync**](../../api-references/c/pfcore/functions/pfuninitializeasync.md) to tear down Core: + +```cpp +XAsyncBlock asyncCore{}; +HRESULT hr = PFUninitializeAsync(&asyncCore); +hr = XAsyncGetStatus(&asyncCore, true); // Blocking wait +``` + +> [!NOTE] +> If you didn't call __PFInitialize__ explicitly, you can skip __PFUninitializeAsync__. In that case, [__PFServicesUninitializeAsync__](../../api-references/c/pfservices/functions/pfservicesuninitializeasync.md) handles Core cleanup automatically. However, if you did call __PFInitialize__ yourself, you must call [__PFUninitializeAsync__](../../api-references/c/pfcore/functions/pfuninitializeasync.md) yourself. + +## Complete example + +This example shows the full lifecycle from initialization through shutdown on a Windows title: + +```cpp +#include + +void RunPlayFab() +{ + // + // Optional: set custom memory hooks + // + PFMemoryHooks hooks{}; + hooks.alloc = MyAllocFunction; + hooks.free = MyFreeFunction; + HRESULT hr = PFMemSetFunctions(&hooks); + + // + // Initialize Core + // + hr = PFInitialize(nullptr); + + // + // Create a service configuration + // + PFServiceConfigHandle serviceConfigHandle{ nullptr }; + hr = PFServiceConfigCreateHandle( + "https://ABCDEF.playfabapi.com", + "ABCDEF", + &serviceConfigHandle); + + // + // Initialize Services + // + hr = PFServicesInitialize(nullptr); + + // + // Log in a player (Windows example using XUser) + // + PFAuthenticationLoginWithXUserRequest request{}; + request.createAccount = true; + request.user = userHandle; + + XAsyncBlock asyncLogin{}; + hr = PFAuthenticationLoginWithXUserAsync(serviceConfigHandle, &request, &asyncLogin); + hr = XAsyncGetStatus(&asyncLogin, true); + + size_t bufferSize{}; + hr = PFAuthenticationLoginWithXUserGetResultSize(&asyncLogin, &bufferSize); + + std::vector loginResultBuffer(bufferSize); + PFAuthenticationLoginResult const* loginResult{}; + PFEntityHandle entityHandle{ nullptr }; + hr = PFAuthenticationLoginWithXUserGetResult( + &asyncLogin, &entityHandle, + loginResultBuffer.size(), loginResultBuffer.data(), + &loginResult, nullptr); + + // + // ... make service calls ... + // + + // + // Shutdown: close handles first + // + PFEntityCloseHandle(entityHandle); + entityHandle = nullptr; + + PFServiceConfigCloseHandle(serviceConfigHandle); + serviceConfigHandle = nullptr; + + // + // Shutdown: uninitialize Services, then Core + // + XAsyncBlock asyncServices{}; + hr = PFServicesUninitializeAsync(&asyncServices); + hr = XAsyncGetStatus(&asyncServices, true); + + XAsyncBlock asyncCore{}; + hr = PFUninitializeAsync(&asyncCore); + hr = XAsyncGetStatus(&asyncCore, true); +} +``` + +## Common mistakes + +| Mistake | What happens | Fix | +|---|---|---| +| Calling [**PFMemSetFunctions**](../../api-references/c/pfplatform/functions/pfmemsetfunctions.md) after [**PFInitialize**](../../api-references/c/pfcore/functions/pfinitialize.md) | The call fails. Memory hooks can only be set before initialization. | Move [**PFMemSetFunctions**](../../api-references/c/pfplatform/functions/pfmemsetfunctions.md) to the very first PlayFab call in your program. | +| Calling [**PFUninitializeAsync**](../../api-references/c/pfcore/functions/pfuninitializeasync.md) before [**PFServicesUninitializeAsync**](../../api-references/c/pfservices/functions/pfservicesuninitializeasync.md) | Undefined behavior. Core is torn down while Services still depends on it. | Always uninitialize Services first, wait for completion, then uninitialize Core. | +| Forgetting to call [**PFUninitializeAsync**](../../api-references/c/pfcore/functions/pfuninitializeasync.md) after explicit [**PFInitialize**](../../api-references/c/pfcore/functions/pfinitialize.md) | Core resources leak. The background queue and HTTP layer aren't cleaned up. | If you called [**PFInitialize**](../../api-references/c/pfcore/functions/pfinitialize.md), you must call [**PFUninitializeAsync**](../../api-references/c/pfcore/functions/pfuninitializeasync.md). | +| Not waiting for async uninitialize to complete | The process may exit while cleanup is still in progress, causing crashes or hangs. | Use `XAsyncGetStatus(async, true)` or an __XAsyncBlock__ callback to wait for completion. | +| Leaking __PFServiceConfigHandle__ or __PFEntityHandle__ | Ref-counted resources aren't freed and may prevent clean shutdown. | Close every handle you create or duplicate before calling uninitialize. | + +## See also + +- [Quickstart: Win32](quickstart-win32.md) +- [Quickstart: Windows](quickstart-gdk.md) +- [Debug Tracing](tracing.md) +- [Asynchronous Programming Model](/gaming/gdk/_content/gc/system/overviews/async-programming-model) diff --git a/playfab-docs/sdks/c/memory.md b/playfab-docs/sdks/c/memory.md index f2cb2504d..53f84539b 100644 --- a/playfab-docs/sdks/c/memory.md +++ b/playfab-docs/sdks/c/memory.md @@ -17,20 +17,26 @@ With the C API in the PlayFab Services SDK, you can specify a function callback To manually specify your memory routines, you can take the following steps: * At the start of the game: - * Call **PFMemSetFunctions** to specify the allocation callbacks for assigning and releasing memory. - * Call **PFServicesInitialize** to initialize the library instance. + * Call [**PFMemSetFunctions**](../../api-references/c/pfplatform/functions/pfmemsetfunctions.md) to specify the allocation callbacks for assigning and releasing memory. + * Call [**PFInitialize**](../../api-references/c/pfcore/functions/pfinitialize.md) to initialize the PlayFab Core library. + * Call [**PFServicesInitialize**](../../api-references/c/pfservices/functions/pfservicesinitialize.md) to initialize the PlayFab Services library. + +> [!IMPORTANT] +> The order matters. **PFMemSetFunctions** must come before **PFInitialize**, and **PFInitialize** must come before **PFServicesInitialize**. If you skip the explicit **PFInitialize** call, **PFServicesInitialize** initializes Core internally—but at that point your memory hooks aren't applied yet, so the SDK uses default allocation routines instead. ```cpp PFMemoryHooks playFabHooks{ MyAllocHook, MyFreeHook }; PFMemSetFunctions(&playFabHooks); - HRESULT hr = PFServicesInitialize(nullptr); // Add your own error handling when FAILED(hr) == true + HRESULT hr = PFInitialize(nullptr); // Add your own error handling when FAILED(hr) == true + hr = PFServicesInitialize(nullptr); // Add your own error handling when FAILED(hr) == true ``` * While the game is running: - * Any calls into the SDK that allocate or free memory will call the specified memory handling callbacks. + * Any calls into the SDK that allocate or free memory call the specified memory handling callbacks. * When the game exits: - * Call **PFServicesUninitializeAsync** to reclaim all resources associated with the SDK. + * Call [**PFServicesUninitializeAsync**](../../api-references/c/pfservices/functions/pfservicesuninitializeasync.md) to reclaim all resources associated with PlayFab Services. + * Call [**PFUninitializeAsync**](../../api-references/c/pfcore/functions/pfuninitializeasync.md) to reclaim all resources associated with PlayFab Core. * Clean up your game's custom memory manager. ## Reference diff --git a/playfab-docs/sdks/c/relogin.md b/playfab-docs/sdks/c/relogin.md index 0f9d327b1..85d3bfc0e 100644 --- a/playfab-docs/sdks/c/relogin.md +++ b/playfab-docs/sdks/c/relogin.md @@ -18,7 +18,7 @@ The PlayFab Services SDK includes a background token refresh mechanism that help The SDK runs a background worker that periodically checks the player's entity token. If the token is **still valid but approaching expiration** (within one hour of expiry), the SDK automatically reauthenticates using the credentials from the original sign-in call. If this refresh succeeds, the token is updated transparently and the **PFEntityHandle** continues to be valid. No action is required from your game. -You can observe these silent token refreshes by registering a **PFEntityRegisterTokenRefreshedEventHandler** callback (see [Transparent refresh](#transparent-refresh)). +You can observe these silent token refreshes by registering a [**PFEntityRegisterTokenRefreshedEventHandler**](../../api-references/c/pfentity/functions/pfentityregistertokenrefreshedeventhandler.md) callback (see [Transparent refresh](#transparent-refresh)). ## When your game must handle token expiration @@ -28,11 +28,11 @@ There are scenarios where the SDK **can't** automatically refresh the token: - **The original sign-in credentials are no longer valid.** If the handle or token originally provided to the sign-in request is no longer valid, automatic refresh fails and the **TokenExpiredHandler** is invoked. > [!IMPORTANT] -> Registering a **PFEntityTokenExpiredEventHandler** is recommended for all titles and is **essential** for GDK titles that support suspend and resume. Without this handler, your game has no way to recover from an expired token. +> Registering a [**PFEntityTokenExpiredEventHandler**](../../api-references/c/pfentity/functions/pfentitytokenexpiredeventhandler.md) is recommended for all titles and is **essential** for GDK titles that support suspend and resume. Without this handler, your game has no way to recover from an expired token. ### Registering the TokenExpiredHandler -Use **PFEntityRegisterTokenExpiredEventHandler** to register for a callback and **PFAuthenticationReLoginWith\*Async** to reauthenticate when the token expires. +Use [**PFEntityRegisterTokenExpiredEventHandler**](../../api-references/c/pfentity/functions/pfentityregistertokenexpiredeventhandler.md) to register for a callback and **PFAuthenticationReLoginWith\*Async** to reauthenticate when the token expires. ```cpp PFRegistrationToken registrationTokenExpired{}; diff --git a/playfab-docs/sdks/c/server.md b/playfab-docs/sdks/c/server.md index e64785abe..473ef2790 100644 --- a/playfab-docs/sdks/c/server.md +++ b/playfab-docs/sdks/c/server.md @@ -20,7 +20,7 @@ Note: At the moment, server functions are only available on the Win32 version of ## Authenticating a title entity -After you create a __PFServiceConfigHandle__ in the initial steps, you can then get a title entity handle by calling __PFAuthenticationGetEntityWithSecretKeyAsync__. After the get entity call completes successfully, it will return __S_OK__ along with a __PFEntityHandle__. This process is similar to logging in as a player. The return type of __PFEntityHandle__ is the same, except in this case the entity handle represents a title entity rather than a player entity. We can call this entity a game server. +After you create a __PFServiceConfigHandle__ in the initial steps, you can then get a title entity handle by calling [__PFAuthenticationGetEntityWithSecretKeyAsync__](../../api-references/c/pfauthentication/functions/pfauthenticationgetentitywithsecretkeyasync.md). After the get entity call completes successfully, it will return __S_OK__ along with a __PFEntityHandle__. This process is similar to logging in as a player. The return type of __PFEntityHandle__ is the same, except in this case the entity handle represents a title entity rather than a player entity. We can call this entity a game server. ```cpp PFAuthenticationGetEntityRequest request{}; diff --git a/playfab-docs/sdks/c/tracing.md b/playfab-docs/sdks/c/tracing.md index fb3a23cf7..3309dd513 100644 --- a/playfab-docs/sdks/c/tracing.md +++ b/playfab-docs/sdks/c/tracing.md @@ -44,6 +44,16 @@ void CALLBACK TraceCallback( HCTraceSetClientCallback(TraceCallback); ``` +## Write traces to a file + +To write PlayFab trace output to a log file on disk, call [**PFTraceEnableTraceToFile**](../../api-references/c/pftrace/functions/pftraceenabletracetofile.md) with the directory where the trace file should be created. Call this function after initialization. + +```cpp +PFTraceEnableTraceToFile("C:\\GameLogs\\PlayFabTraces"); +``` + +This function is independent of the HCTrace functions above. You can use file tracing alongside debugger output and client callbacks. + ## Reference [PlayFab API reference documentation](../../api-references/c/pftrace/pftrace_members.md) diff --git a/playfab-docs/sdks/toc.yml b/playfab-docs/sdks/toc.yml index d49742c01..1e7531ed8 100644 --- a/playfab-docs/sdks/toc.yml +++ b/playfab-docs/sdks/toc.yml @@ -41,8 +41,16 @@ items: href: c/quickstart-Linux.md - name: Making Async Calls href: c/async.md + - name: SDK Lifecycle + href: c/lifecycle.md + - name: Entity Handles + href: c/entity-handles.md - name: Managing Memory href: c/memory.md + - name: HTTP Configuration + href: c/http-config.md + - name: Handling Errors + href: c/errors.md - name: Handling Token Expiration href: c/relogin.md - name: Debug Tracing From 3263d3b172160d5ed7f0cb36a1547560cbf1fc8f Mon Sep 17 00:00:00 2001 From: Ernesto Cortes Groman Date: Wed, 18 Feb 2026 11:33:24 -0800 Subject: [PATCH 47/76] Update EconomV2 docs (#2821) Co-authored-by: Ernesto Cortes Groman --- .../economy-v2/catalog/catalog-overview.md | 2 +- .../economy-v2/catalog/subscriptions.md | 8 +-- .../economy-v2/fraud-prevention/index.md | 2 +- .../economy-v2/inventory/collections.md | 2 +- .../economy-v2/inventory/index.md | 38 +++++++++++++ .../inventory/items-and-inventory-overview.md | 57 +++++++++++++------ .../economy-v2/inventory/stacks.md | 2 +- .../economy-v2/inventory/turboloading.md | 4 +- .../economy-monetization/economy-v2/limits.md | 6 +- .../economy-v2/overview.md | 6 -- .../economy-v2/settings.md | 2 +- 11 files changed, 91 insertions(+), 38 deletions(-) diff --git a/playfab-docs/economy-monetization/economy-v2/catalog/catalog-overview.md b/playfab-docs/economy-monetization/economy-v2/catalog/catalog-overview.md index 19ae49a5e..a31682edf 100644 --- a/playfab-docs/economy-monetization/economy-v2/catalog/catalog-overview.md +++ b/playfab-docs/economy-monetization/economy-v2/catalog/catalog-overview.md @@ -37,7 +37,7 @@ Tab | Description | Reference **Stores** | Stores allow you to override base catalog prices for items. | [PlayFab Economy V2 Stores](stores.md) **Subscriptions** | Virtual subscriptions allow you to grant time based access to durable goods. | [PlayFab Economy V2 Subscriptions](subscriptions.md). -Each of these is an Item Type that can be used within your Catalog. Bundles +Each of these is an Item Type that can be used within your Catalog. ### Catalog V2 item fields diff --git a/playfab-docs/economy-monetization/economy-v2/catalog/subscriptions.md b/playfab-docs/economy-monetization/economy-v2/catalog/subscriptions.md index 32fbd8d08..3dc9ba524 100644 --- a/playfab-docs/economy-monetization/economy-v2/catalog/subscriptions.md +++ b/playfab-docs/economy-monetization/economy-v2/catalog/subscriptions.md @@ -15,11 +15,11 @@ ms.localizationpriority: medium Subscriptions allow you to grant time based access to durable goods. Items within a subscription are unpacked in a player's inventory after calling [GetInventoryItems](/rest/api/playfab/economy/inventory/get-inventory-items). > [!NOTE] ->This article focuses on virtual subscriptions, or the subscriptions that live inside of your game. We have a new feature in **Private Preview** where you can link virtual subscriptions to real-world marketplaces using PlayFab's Inventory Redeem APIs. Here is where you can find more information about how to do this: ->- [IOS Subscription Redemption](../marketplace/marketplace-redemption/ios-subscription-redemption.md) ->- [Google Play Store Subscription Redemption](../marketplace/marketplace-redemption/google-subscription-redemption.md) +> This article focuses on virtual subscriptions, or the subscriptions that live inside of your game. We have a feature in **Private Preview** where you can link virtual subscriptions to real-world marketplaces using PlayFab's Inventory Redeem APIs. Here is where you can find more information about how to do this: +> - [iOS Subscription Redemption](../marketplace/marketplace-redemption/ios-subscription-redemption.md) +> - [Google Play Store Subscription Redemption](../marketplace/marketplace-redemption/google-subscription-redemption.md) > ->To access this feature, send an email to **PFEconomyPreviews@microsoft.com** with the subject **PlayFab Mobile Subscriptions** along with your PlayFab Title ID and we will enable the feature in your environment. +> To access this feature, send an email to **PFEconomyPreviews@microsoft.com** with the subject **PlayFab Mobile Subscriptions** along with your PlayFab Title ID and we will enable the feature in your environment. ## Creating a Subscription diff --git a/playfab-docs/economy-monetization/economy-v2/fraud-prevention/index.md b/playfab-docs/economy-monetization/economy-v2/fraud-prevention/index.md index fb3d42350..ccb6f4887 100644 --- a/playfab-docs/economy-monetization/economy-v2/fraud-prevention/index.md +++ b/playfab-docs/economy-monetization/economy-v2/fraud-prevention/index.md @@ -14,7 +14,7 @@ ms.localizationpriority: medium [!INCLUDE [notice](../../../includes/_economy-release.md)] -The heart of any game economy is allowing players to purchase game items, currencies, and more with virtual currencies or Real Word (RW) money. +The heart of any game economy is allowing players to purchase game items, currencies, and more with virtual currencies or real-world (RW) money. ## Fraud Vectors diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/collections.md b/playfab-docs/economy-monetization/economy-v2/inventory/collections.md index 8c06659b5..5a1d3941d 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/collections.md +++ b/playfab-docs/economy-monetization/economy-v2/inventory/collections.md @@ -74,7 +74,7 @@ For example, the following `AddInventoryItems` request uses the collectionId `ma } ``` -The above request would either create a brand new inventory collection of and add 5 of the item to it or add 5 to the existing `main_character` inventory collection if it already existed. +The above request would either create a brand new `main_character` inventory collection and add 10 of the item to it, or add 10 to the existing `main_character` inventory collection if it already existed. ### DeleteInventoryCollection diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/index.md b/playfab-docs/economy-monetization/economy-v2/inventory/index.md index 3adef32fb..eb248fe2e 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/index.md +++ b/playfab-docs/economy-monetization/economy-v2/inventory/index.md @@ -158,6 +158,9 @@ An example `PurchaseInventoryItems` request: } ``` +> [!NOTE] +> The `PurchaseInventoryItems` API is used for purchases with virtual currencies. For real-money purchases through external marketplaces (Apple App Store, Google Play, Steam, Microsoft Store), use the corresponding Redeem APIs (such as `RedeemAppleAppStoreInventoryItems`, `RedeemGooglePlayInventoryItems`, `RedeemSteamInventoryItems`, or `RedeemMicrosoftStoreInventoryItems`). These APIs validate the purchase receipt with the marketplace and grant the items to the player's inventory. For more information, see [Marketplace Redemption](../marketplace/marketplace-redemption/overview.md). + ### Transfer Inventory Items The `TransferInventoryItems` API can be used in three different ways. @@ -334,6 +337,41 @@ For example, the following `PurchaseItem` API request can be called multiple tim > [!NOTE] > Using the same `IdempotencyId` for different request types will cause a conflict and throw an error. +### ETags and Conditional Operations + +Inventory operations support ETags for optimistic concurrency control. When you retrieve a player's inventory using `GetInventoryItems`, the response includes an `ETag` value that represents the current state of the inventory collection. + +You can use this `ETag` value in subsequent write operations (such as `AddInventoryItems`, `SubtractInventoryItems`, `UpdateInventoryItems`, `DeleteInventoryItems`, `PurchaseInventoryItems`, `TransferInventoryItems`, and `ExecuteInventoryOperations`) to ensure the inventory hasn't been modified since you last read it. If the inventory has changed since the `ETag` was retrieved, the operation fails with a conflict error, preventing concurrent modifications from silently overwriting each other. + +ETags are passed via HTTP headers on the request: + +- **`X-PlayFab-Economy-If-Match`** - The operation only succeeds if the current inventory ETag matches the provided value. Use this to ensure you're modifying the expected state. +- **`X-PlayFab-Economy-If-None-Match`** - The operation only succeeds if the current inventory ETag does **not** match the provided value. Use this to prevent overwriting a known state. + +This is useful in scenarios where multiple systems or game clients may be modifying the same player's inventory simultaneously, and you need to ensure that operations are applied to the expected state. + +An example `SubtractInventoryItems` request with an ETag header: + +```http +POST /Inventory/SubtractInventoryItems +Content-Type: application/json +X-PlayFab-Economy-If-Match: "1a2b3c4d-5e6f-7890-abcd-ef1234567890" + +{ + "Entity": { + "Type": "title_player_account", + "Id": "ABCD12345678" + }, + "Item": { + "Id": "0b440353-bdbc-48d8-8873-f0988c1f9d8b", + }, + "Amount": 5 +} +``` + +> [!NOTE] +> If the ETag provided in `X-PlayFab-Economy-If-Match` does not match the current state of the inventory, the API returns a conflict error. You should retrieve the latest inventory state and retry the operation with the updated ETag. + ### Display Properties Display Properties are custom item properties that can be added to items and item stacks in player inventories. diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/items-and-inventory-overview.md b/playfab-docs/economy-monetization/economy-v2/inventory/items-and-inventory-overview.md index ff1f6daa1..e9e524601 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/items-and-inventory-overview.md +++ b/playfab-docs/economy-monetization/economy-v2/inventory/items-and-inventory-overview.md @@ -1,40 +1,61 @@ --- title: Items and Inventory Overview author: thomasgu -description: Overall description of Items and Inventory in V2. +description: Overview of Economy v2 Items and Inventory concepts and APIs. ms.author: thomg ms.date: 02/20/2025 ms.topic: article ms.service: azure-playfab -keywords: playfab, commerce, economy, items, catalogs +keywords: playfab, commerce, economy, items, catalogs, inventory, v2 ms.localizationpriority: medium --- # PlayFab Items and Inventory Overview -Items and inventories are essential features for creating engaging and immersive games. They allow you to offer customization options, rewards, progression systems, and monetization opportunities for your players. +[!INCLUDE [notice](../../../includes/_economy-release.md)] -PlayFab provides a flexible and powerful platform for creating and managing these virtual goods. You can use PlayFab to define different types of items, such as durables, consumables, bundles, containers, and more. You can also use PlayFab to track the ownership and usage of items by your players. Here are some of the key concepts you need to know about items and inventories in PlayFab: +Items and inventories are essential features for creating engaging and immersive games. They allow you to offer customization options, rewards, progression systems, and monetization opportunities for your players. -[!INCLUDE [notice](../../../includes/_economy-deprecation.md)] +PlayFab Economy v2 provides a flexible and powerful platform for creating and managing virtual goods. You can define different types of items — such as durables, consumables, bundles, subscriptions, and virtual currencies — and track the ownership and usage of items across your players' inventories. ## Key concepts -* **Catalog** - A catalog is a collection of all the items that are available in your game. Catalogs offer an easy way to manage your game's virtual items. -* **Catalog Items** – Catalog items are the individual items that you define in your catalog. They can represent any kind of virtual good that you want to offer in your game, such as weapons, outfits, power-ups, loot boxes, etc. You can customize the properties and behaviors of catalog items to suit your game design. -* **Catalog Stores** - You can use store create multiple item listings for different purposes, such as seasonal events, promotions, or testing. -* **Player Inventory Collections** - Inventory is a record of the items that a player owns or has used in your game. It also contains information about the player's virtual currency balances and item history. All player accounts can have one or more inventories, which we call inventory collections. -* **Virtual Currency** - Virtual currency is a type of item that can be used as a medium of exchange in your game. You commonly use virtual currency to sell or buy other items from the catalog or a store. You can also use virtual currency to implement soft currency conversions from in-app purchases or to drive gameplay mechanics. - -For more information about these and other related concepts, please refer to the [Economy V2 Catalog Overview](../catalog/catalog-overview.md) +* **Catalog** - A catalog is a collection of all the items that are available in your game. Catalogs offer an easy way to manage your game's virtual items. For more information, see the [Catalog Overview](../catalog/catalog-overview.md). +* **Catalog Items** – Individual items defined in your catalog. They can represent any kind of virtual good, such as weapons, outfits, power-ups, loot boxes, etc. You can customize properties and behaviors to suit your game design. +* **Catalog Stores** - Stores allow you to create multiple item listings for different purposes, such as seasonal events, promotions, or testing. See [Stores](../catalog/stores.md). +* **Bundles** - Bundles are catalog items that contain references to other items. When a player purchases a bundle, the referenced items are unpacked and added to their inventory. +* **Subscriptions** - Subscriptions grant time-based access to durable goods. Items within a subscription are available in a player's inventory for the duration of the subscription. See [Subscriptions](../catalog/subscriptions.md). +* **Player Inventory Collections** - Inventory is a record of the items that a player owns in your game. It contains information about item amounts, virtual currency balances, and custom properties. All player accounts can have one or more inventories called [Collections](collections.md). +* **Stacks** - Stacks allow multiple distinct instances of the same item to exist within a single inventory, each with their own amount and custom properties. See [Stacks](stacks.md). +* **Virtual Currency** - Virtual currency is a type of item used as a medium of exchange in your game. You can use virtual currency to buy items from the catalog or a store, implement soft currency from in-app purchases, or drive gameplay mechanics. ## Key APIs -PlayFab provides a large interactive playing field for interaction with items and inventory, and the Item definition in the Catalog allows for quite a bit of customization. A rich set of APIs is available for interacting with items and inventories in your game. You can use these APIs to perform various actions, such as purchasing items, granting items, consuming items, updating inventory, and querying inventory. Most common interactions are through a few key APIs: +A rich set of APIs is available for interacting with items and inventories in your game. You can use these APIs to perform actions such as purchasing items, granting items, updating inventory, transferring items between players, and querying transaction history. + +### Inventory Management + +* **[GetInventoryItems](/rest/api/playfab/economy/inventory/get-inventory-items)** - Retrieve the current inventory of an entity. Supports pagination with `ContinuationToken` and bulk loading via [TurboLoading](turboloading.md). +* **[AddInventoryItems](/rest/api/playfab/economy/inventory/add-inventory-items)** - Add items directly to a player's inventory. +* **[SubtractInventoryItems](/rest/api/playfab/economy/inventory/subtract-inventory-items)** - Reduce item amounts in a player's inventory. +* **[UpdateInventoryItems](/rest/api/playfab/economy/inventory/update-inventory-items)** - Set item amounts or modify [Display Properties](index.md#display-properties) on inventory items. +* **[DeleteInventoryItems](/rest/api/playfab/economy/inventory/delete-inventory-items)** - Remove entire stacks of items from a player's inventory. + +### Purchasing and Trading + +* **[PurchaseInventoryItems](/rest/api/playfab/economy/inventory/purchase-inventory-items)** - Buy catalog items or bundles using virtual currency. Deducts the currency from the player's inventory and grants the purchased item. +* **[TransferInventoryItems](/rest/api/playfab/economy/inventory/transfer-inventory-items)** - Transfer items between players, between a player's inventory collections, or between stacks within the same inventory. + +### Batch Operations + +* **[ExecuteInventoryOperations](/rest/api/playfab/economy/inventory/execute-inventory-operations)** - Batch up to 10 inventory operations (Add, Subtract, Update, Purchase, Transfer, Delete) in a single atomic request. If any operation fails, the entire batch is rolled back. + +### History and Diagnostics + +* **[GetTransactionHistory](/rest/api/playfab/economy/inventory/get-transaction-history)** - Retrieve transaction events from a player's inventory. Supports filtering by timestamp and pagination for reviewing the full operation history. See [Transaction History](transaction-history.md). + +### Reliability -* **PurchaseInventoryItems** - This API allows a player to buy catalog items or bundles with virtual currency. It deducts the currency from the player's inventory and adds an item instance to the player's inventory. -* **GetInventoryItems** - Allows you to retrieve the current inventory of an Entity, and will return a list of item instances for the specified player. -* **UpdateInventoryItems** - Used to make convenient changes to inventory items, especially to DisplayProperties for modifying custom attributes. -* **GetTransactionHistory** - Will get the latest transaction events from the inventory, and allow you to page through to get the full transaction history. +* **Idempotency** - All inventory APIs support an `IdempotencyId` parameter to safely retry requests without duplicate side effects. IDs are enforced for 14 days. See [Idempotency](index.md#idempotency). -For more information on how to use these APIs and other related APIs, please refer to the [PlayFab Inventory API documentation](/rest/api/playfab/economy/inventory?view=playfab-rest) +For the full API reference and detailed examples for each operation, see the [Inventory API documentation](index.md) and the [PlayFab REST API reference](/rest/api/playfab/economy/inventory). diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/stacks.md b/playfab-docs/economy-monetization/economy-v2/inventory/stacks.md index 35f1101fe..07b265cf8 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/stacks.md +++ b/playfab-docs/economy-monetization/economy-v2/inventory/stacks.md @@ -120,7 +120,7 @@ When you make purchases with stacks, there are a few parameters that are relevan - For the `Item` object, you can define an optional `StackId` that represents the stack the receiving items will be placed in - There's a`DeleteEmptyStacks` boolean that can be set which deletes the stack if the subtracted amount results in the stack having an amount of 0. -> TODO Add link +For more information about the `PurchaseInventoryItems` API, see the [Inventory APIs documentation](index.md#purchase-inventory-items). An example `PurchaseInventoryItems` request with stacks: diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/turboloading.md b/playfab-docs/economy-monetization/economy-v2/inventory/turboloading.md index 524cde976..4154aad5e 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/turboloading.md +++ b/playfab-docs/economy-monetization/economy-v2/inventory/turboloading.md @@ -44,14 +44,14 @@ You can enable compression for all API responses using the Cross-Platform PlayFa // Initialize PFHttpSettings struct PFHttpSettings* httpSettings = new PFHttpSettings; -// Enable Repsonse Compression (and automatic decompression) +// Enable Response Compression (and automatic decompression) httpSettings->requestResponseCompression = true; // Set PFHttpSettings HRESULT hr = PFSetHttpSettings(httpSettings); // Add your own error handling FAILED(hr) == true ``` -Additionally you can disable compression for all API reponses: +Additionally you can disable compression for all API responses: ```C++ // Disable Response Compression httpSettings->requestResponseCompression = false; diff --git a/playfab-docs/economy-monetization/economy-v2/limits.md b/playfab-docs/economy-monetization/economy-v2/limits.md index cc9e76e92..89a8a1a49 100644 --- a/playfab-docs/economy-monetization/economy-v2/limits.md +++ b/playfab-docs/economy-monetization/economy-v2/limits.md @@ -62,7 +62,7 @@ The purpose of this guide is to detail the limits that are enforced when creatin > [!NOTE] > > - Inventory throttling will be calculated based on the target entity, individually for each API. -> - For example, if a Player or a Title (game service, coudscript, etc.) calls an Inventory API to update the Player entity's inventory, the Limit (Player) throttling will be applied. +> - For example, if a Player or a Title (game service, CloudScript, etc.) calls an Inventory API to update the Player entity's inventory, the Limit (Player) throttling will be applied. > - [Group entity](../../live-service-management/game-configuration/entities/index.md#group) inventories are also supported, and Group Entities share the same throttling rate as Player entities. See also [Groups](../../community/associations/groups/index.md). ### Read @@ -97,7 +97,7 @@ The purpose of this guide is to detail the limits that are enforced when creatin |---------|--------------------|-------------------| | **RedeemAppleAppStoreInventoryItems** | 0.16 rps (10 in 60 seconds) | - | | **RedeemGooglePlayInventoryItems** | 0.16 rps (10 in 60 seconds) | - | -| **RedeemMicrosoftStoreInventorItems** | 0.16 rps (10 in 60 seconds) | - | +| **RedeemMicrosoftStoreInventoryItems** | 0.16 rps (10 in 60 seconds) | - | | **RedeemNintendoEShopInventoryItems** | 0.16 rps (10 in 60 seconds) | - | | **RedeemPlayStationStoreInventoryItems** | 0.16 rps (10 in 60 seconds) | - | | **RedeemSteamInventoryItems** | 0.16 rps (10 in 60 seconds) | - | @@ -166,7 +166,7 @@ Up to 20GB of catalog data are allowed per Catalog creator entity. This limit is ### Titles -Tiles have a **512 character limit** per country code. +Titles have a **512 character limit** per country code. ### Descriptions diff --git a/playfab-docs/economy-monetization/economy-v2/overview.md b/playfab-docs/economy-monetization/economy-v2/overview.md index c789d597f..153520dde 100644 --- a/playfab-docs/economy-monetization/economy-v2/overview.md +++ b/playfab-docs/economy-monetization/economy-v2/overview.md @@ -29,12 +29,6 @@ Economy v2 is designed with the same flexibility and extensibility that you woul Interested to find out why we made Economy V2 and how you can use the improvements in your title? >[!VIDEO https://www.youtube.com/embed/NcvFFgTZ6ek] -#### PlayFab Economy v2 - -Provides an introduction to the Azure PlayFab Economy v2 and discusses key improvements in V2. - ->[!VIDEO https://www.youtube.com/embed/NcvFFgTZ6ek] - ## Which version of Economy should I use? You should use version 2. If you're on version 1, you should look at upgrading. Although we're _not_ deprecating v1 and will maintain and support it for all titles, it's in bugfix-only mode. The new Economy features are being developed only for version 2. For more information on the differences between the two versions, see [FAQ](faq.md). diff --git a/playfab-docs/economy-monetization/economy-v2/settings.md b/playfab-docs/economy-monetization/economy-v2/settings.md index 7dc331317..8498e374c 100644 --- a/playfab-docs/economy-monetization/economy-v2/settings.md +++ b/playfab-docs/economy-monetization/economy-v2/settings.md @@ -14,7 +14,7 @@ ms.localizationpriority: medium [!INCLUDE [notice](../../includes/_economy-release.md)] -Economy v2 includes the following configuration that can be updated in Game Manager bg selecting **Economy** > **Catalog (V2)** then **⚙️ Settings**. +Economy v2 includes the following configuration that can be updated in Game Manager by selecting **Economy** > **Catalog (V2)** then **⚙️ Settings**. These settings can also be set and accessed via APIs using the [UpdateCatalogConfig](/rest/api/playfab/economy/catalog/update-catalog-config) and [GetCatalogConfig](/rest/api/playfab/economy/catalog/get-catalog-config) calls respectively. Catalog Config APIs can only be called by [title entities](../../live-service-management/game-configuration/entities/index.md#title). From fffe6e4aca91c097a8ffbc325710c1900b776ef2 Mon Sep 17 00:00:00 2001 From: anaisnlawson Date: Wed, 18 Feb 2026 15:50:42 -0500 Subject: [PATCH 48/76] Remove duplicates + fix description (#2823) * removed duplicates * shorten description --- .../player-ranked-on-leaderboard-version.md | 2 +- playfab-docs/api-references/events/index.md | 59 +------------------ 2 files changed, 2 insertions(+), 59 deletions(-) diff --git a/playfab-docs/api-references/events/Leaderboards/player-ranked-on-leaderboard-version.md b/playfab-docs/api-references/events/Leaderboards/player-ranked-on-leaderboard-version.md index dde7d02f2..81994a4ff 100644 --- a/playfab-docs/api-references/events/Leaderboards/player-ranked-on-leaderboard-version.md +++ b/playfab-docs/api-references/events/Leaderboards/player-ranked-on-leaderboard-version.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # player_ranked_on_leaderboard_version -This event is triggered for the top-ranked players on a leaderboard when the leaderboard version changes (e.g. when a leaderboard statistic version is incremented). The maximum number of leaderboard entries for which the event is generated is controlled by the "Leaderboard version change top rank events sent" title limit. +This event is triggered when a leaderboard version changes, generating events for top‑ranked players up to the limit defined by the "Leaderboard version change top rank events sent" setting. ## Properties diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 02940d8aa..41f8fe880 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -158,17 +158,6 @@ Each event type has a set of properties that are included as part of event's dat - [group_updated](Groups/group-updated.md) This event is triggered when an entity group is updated. -- [studio_created](studio-created.md) - This event is triggered when a studio is created. - -- [studio_user_added](studio-user-added.md) - This event is triggered when a user accepts a studio invitation. - -- [studio_user_invited](studio-user-invited.md) - This event is triggered when a user is invited to a studio. - -- [studio_user_removed](studio-user-removed.md) - This event is triggered when a user is removed from a studio. - [members_added](Groups/members-added.md) This event is triggered when members are added to a group. @@ -418,9 +407,6 @@ Each event type has a set of properties that are included as part of event's dat - [player_paid_for_purchase](player-paid-for-purchase.md) This event is triggered when the second step of the payment process completes, paying for the purchase. -- [player_ranked_on_leaderboard_version](player-ranked-on-leaderboard-version.md) - This event is triggered for the top-ranked players on a leaderboard when the leaderboard version changes (e.g. when a leaderboard statistic version is incremented). The maximum number of leaderboard entries for which the event is generated is controlled by the "Leaderboard version change top rank events sent" title limit. - - [player_realmoney_purchase](player-realmoney-purchase.md) This event is triggered when a player makes a real money purchase, and generates revenue for the game. @@ -436,12 +422,6 @@ Each event type has a set of properties that are included as part of event's dat - [player_started_purchase](player-started-purchase.md) This event is triggered when a player starts a purchase. -- [player_statistic_changed](player-statistic-changed.md) - This event is triggered when a player statistic is changed. - -- [player_statistic_deleted](player-statistic-deleted.md) - This event is triggered when a player statistic is deleted. - - [player_vc_item_purchased](player-vc-item-purchased.md) This event is triggered when the player makes a purchase using virtual currency. @@ -498,8 +478,6 @@ Each event type has a set of properties that are included as part of event's dat - [player_removed_title](PlayerIdentity/player-removed-title.md) This event is triggered when a player account for a title is removed. Note: this event is triggered once per title rather than once per publisher. -- [player_realmoney_purchase](player-realmoney-purchase.md) - This event is triggered when a player makes a real money purchase, and generates revenue for the game. - [player_reported_as_abusive](PlayerIdentity/player-reported-as-abusive.md) This event is triggered when a player is reported by another player as abusive. @@ -527,8 +505,6 @@ Each event type has a set of properties that are included as part of event's dat - [title_profile_view_constraints_changed](PlayerIdentity/title-profile-view-constraints-changed.md) This event is triggered when a profile view constraint is changed for the title. -- [player_tag_added](player-tag-added.md) - This event is triggered when a tag is added to a player profile. - [entity_deleted](PlayerIdentity/entity-deleted.md) This event is triggered when an entity is deleted. @@ -598,45 +574,12 @@ Each event type has a set of properties that are included as part of event's dat - [title_high_error_rate_alert](title-high-error-rate-alert.md) This event is triggered when a game title experiences a high rate of errors. -- [title_initiated_player_password_reset](title-initiated-player-password-reset.md) - This event is triggered when a title initiates the account recovery process for a player. - -- [title_limit_changed](title-limit-changed.md) - This event is triggered when a title changes a service limit. - -- [title_news_updated](title-news-updated.md) - This event is triggered when a title news is created or updated. - -- [title_permission_policy_changed](title-permission-policy-changed.md) - This event is triggered when an update occurs to a a title's permission policies. - -- [title_profile_view_constraints_changed](title-profile-view-constraints-changed.md) - This event is triggered when a profile view constraint is changed for the title. - -- [title_published_cloudscript](title-published-cloudscript.md) - An inactive revision of CloudScript has been made into the active 'live' version. - -- [title_queue_config_updated](Matchmaking/title-queue-config-updated.md) - This event is triggered when a queue config is changed. - - [title_requested_limit_change](title-requested-limit-change.md) This event is triggered when a title requests a service limit change. - [title_saved_survey](title-saved-survey.md) This event is triggered when a game's survey is saved. -- [title_scheduled_cloudscript_executed](title-scheduled-cloudscript-executed.md) - This event is triggered when a CloudScript function is run by a scheduled task. - -- [title_secret_key_changed](title-secret-key-changed.md) - This event is triggered when a title adds or updates a Secret Key - -- [title_started_task](title-started-task.md) - This event is triggered when a task is scheduled to run. - -- [title_statistic_version_changed](title-statistic-version-changed.md) - This event is triggered when the version of a statistic changes, causing its leaderboard to reset. - - [title_store_updated](title-store-updated.md) This event is triggered when a store is changed. @@ -680,7 +623,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a leaderboard version is reset - [player_ranked_on_leaderboard_version](Leaderboards/player-ranked-on-leaderboard-version.md) - This event is triggered for the top-ranked players on a leaderboard when the leaderboard version changes (e.g. when a leaderboard statistic version is incremented). The maximum number of leaderboard entries for which the event is generated is controlled by the "Leaderboard version change top rank events sent" title limit. + This event is triggered when a leaderboard version changes, generating events for top‑ranked players up to the limit defined by the "Leaderboard version change top rank events sent" setting. - [player_statistic_changed](Leaderboards/player-statistic-changed.md) This event is triggered when a player statistic is changed. From 76eb3e6720ba6922e51fb6e67d09cc3ac035a0ca Mon Sep 17 00:00:00 2001 From: ronnyparedesc <113482725+ronnyparedesc@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:44:44 -0800 Subject: [PATCH 49/76] Update Economy PlayStream Event Documentation (#2792) --- .../{ => CatalogV1}/title-catalog-updated.md | 14 +-- .../events/CatalogV1/title-store-updated.md | 29 ++++++ .../events/CatalogV2/item-created.md | 26 +++++ .../events/CatalogV2/item-deleted.md | 26 +++++ .../item-moderation-state-changed.md | 12 +-- .../{ => CatalogV2}/item-publish-requested.md | 10 +- .../events/CatalogV2/item-purchased.md | 37 +++++++ .../events/CatalogV2/item-reported.md | 29 ++++++ .../events/{ => CatalogV2}/item-updated.md | 10 +- .../events/CatalogV2/review-reported.md | 29 ++++++ .../reviews-takedown-requested.md | 8 +- .../InventoryV1/character-consumed-item.md | 31 ++++++ .../character-inventory-item-added.md | 36 +++++++ .../character-vc-item-purchased.md | 33 +++++++ ...racter-virtual-currency-balance-changed.md | 30 ++++++ .../InventoryV1/player-consumed-item.md | 30 ++++++ .../player-inventory-item-added.md | 35 +++++++ .../InventoryV1/player-paid-for-purchase.md | 35 +++++++ .../InventoryV1/player-realmoney-purchase.md | 33 +++++++ .../InventoryV1/player-receipt-validation.md | 30 ++++++ .../InventoryV1/player-redeemed-coupon.md | 27 +++++ .../InventoryV1/player-started-purchase.md | 29 ++++++ .../InventoryV1/player-vc-item-purchased.md | 32 ++++++ ...player-virtual-currency-balance-changed.md | 29 ++++++ .../events/InventoryV2/items-added.md | 32 ++++++ .../InventoryV2/items-clawback-completed.md | 29 ++++++ .../items-clawback-reversal-completed.md | 29 ++++++ .../events/InventoryV2/items-deleted.md | 29 ++++++ .../events/InventoryV2/items-expired.md | 29 ++++++ .../events/InventoryV2/items-purchased.md | 34 +++++++ .../events/InventoryV2/items-redeemed.md | 34 +++++++ .../events/InventoryV2/items-subtracted.md | 32 ++++++ .../events/InventoryV2/items-transferred.md | 36 +++++++ .../events/InventoryV2/items-updated.md | 31 ++++++ .../marketplace-transaction-redeemed.md | 32 ++++++ .../events/character-consumed-item.md | 31 ------ .../events/character-inventory-item-added.md | 36 ------- .../events/character-vc-item-purchased.md | 33 ------- ...racter-virtual-currency-balance-changed.md | 30 ------ .../data-types/itempurchasedcurrency.md | 22 +++++ .../data-types/itempurchasedoverride.md | 23 +++++ .../itemsclawbackcompletedpayload.md | 32 ++++++ .../itemsclawbackreversalcompletedpayload.md | 32 ++++++ .../events/data-types/itemsexpiredpayload.md | 27 +++++ playfab-docs/api-references/events/index.md | 98 +++++++++++++++---- .../api-references/events/item-created.md | 26 ----- .../api-references/events/item-deleted.md | 26 ----- .../api-references/events/item-reported.md | 29 ------ .../api-references/events/items-added.md | 32 ------ .../api-references/events/items-deleted.md | 29 ------ .../api-references/events/items-purchased.md | 34 ------- .../api-references/events/items-redeemed.md | 34 ------- .../api-references/events/items-subtracted.md | 32 ------ .../events/items-transferred.md | 36 ------- .../api-references/events/items-updated.md | 31 ------ .../marketplace-transaction-redeemed.md | 32 ------ .../events/player-consumed-item.md | 30 ------ .../events/player-inventory-item-added.md | 35 ------- .../events/player-paid-for-purchase.md | 35 ------- .../events/player-realmoney-purchase.md | 33 ------- .../events/player-receipt-validation.md | 30 ------ .../events/player-redeemed-coupon.md | 27 ----- .../events/player-started-purchase.md | 29 ------ .../events/player-vc-item-purchased.md | 32 ------ ...player-virtual-currency-balance-changed.md | 29 ------ .../api-references/events/review-reported.md | 29 ------ .../events/title-store-updated.md | 29 ------ 67 files changed, 1177 insertions(+), 853 deletions(-) rename playfab-docs/api-references/events/{ => CatalogV1}/title-catalog-updated.md (53%) create mode 100644 playfab-docs/api-references/events/CatalogV1/title-store-updated.md create mode 100644 playfab-docs/api-references/events/CatalogV2/item-created.md create mode 100644 playfab-docs/api-references/events/CatalogV2/item-deleted.md rename playfab-docs/api-references/events/{ => CatalogV2}/item-moderation-state-changed.md (51%) rename playfab-docs/api-references/events/{ => CatalogV2}/item-publish-requested.md (54%) create mode 100644 playfab-docs/api-references/events/CatalogV2/item-purchased.md create mode 100644 playfab-docs/api-references/events/CatalogV2/item-reported.md rename playfab-docs/api-references/events/{ => CatalogV2}/item-updated.md (53%) create mode 100644 playfab-docs/api-references/events/CatalogV2/review-reported.md rename playfab-docs/api-references/events/{ => CatalogV2}/reviews-takedown-requested.md (59%) create mode 100644 playfab-docs/api-references/events/InventoryV1/character-consumed-item.md create mode 100644 playfab-docs/api-references/events/InventoryV1/character-inventory-item-added.md create mode 100644 playfab-docs/api-references/events/InventoryV1/character-vc-item-purchased.md create mode 100644 playfab-docs/api-references/events/InventoryV1/character-virtual-currency-balance-changed.md create mode 100644 playfab-docs/api-references/events/InventoryV1/player-consumed-item.md create mode 100644 playfab-docs/api-references/events/InventoryV1/player-inventory-item-added.md create mode 100644 playfab-docs/api-references/events/InventoryV1/player-paid-for-purchase.md create mode 100644 playfab-docs/api-references/events/InventoryV1/player-realmoney-purchase.md create mode 100644 playfab-docs/api-references/events/InventoryV1/player-receipt-validation.md create mode 100644 playfab-docs/api-references/events/InventoryV1/player-redeemed-coupon.md create mode 100644 playfab-docs/api-references/events/InventoryV1/player-started-purchase.md create mode 100644 playfab-docs/api-references/events/InventoryV1/player-vc-item-purchased.md create mode 100644 playfab-docs/api-references/events/InventoryV1/player-virtual-currency-balance-changed.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-added.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-clawback-completed.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-clawback-reversal-completed.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-deleted.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-expired.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-purchased.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-redeemed.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-subtracted.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-transferred.md create mode 100644 playfab-docs/api-references/events/InventoryV2/items-updated.md create mode 100644 playfab-docs/api-references/events/InventoryV2/marketplace-transaction-redeemed.md delete mode 100644 playfab-docs/api-references/events/character-consumed-item.md delete mode 100644 playfab-docs/api-references/events/character-inventory-item-added.md delete mode 100644 playfab-docs/api-references/events/character-vc-item-purchased.md delete mode 100644 playfab-docs/api-references/events/character-virtual-currency-balance-changed.md create mode 100644 playfab-docs/api-references/events/data-types/itempurchasedcurrency.md create mode 100644 playfab-docs/api-references/events/data-types/itempurchasedoverride.md create mode 100644 playfab-docs/api-references/events/data-types/itemsclawbackcompletedpayload.md create mode 100644 playfab-docs/api-references/events/data-types/itemsclawbackreversalcompletedpayload.md create mode 100644 playfab-docs/api-references/events/data-types/itemsexpiredpayload.md delete mode 100644 playfab-docs/api-references/events/item-created.md delete mode 100644 playfab-docs/api-references/events/item-deleted.md delete mode 100644 playfab-docs/api-references/events/item-reported.md delete mode 100644 playfab-docs/api-references/events/items-added.md delete mode 100644 playfab-docs/api-references/events/items-deleted.md delete mode 100644 playfab-docs/api-references/events/items-purchased.md delete mode 100644 playfab-docs/api-references/events/items-redeemed.md delete mode 100644 playfab-docs/api-references/events/items-subtracted.md delete mode 100644 playfab-docs/api-references/events/items-transferred.md delete mode 100644 playfab-docs/api-references/events/items-updated.md delete mode 100644 playfab-docs/api-references/events/marketplace-transaction-redeemed.md delete mode 100644 playfab-docs/api-references/events/player-consumed-item.md delete mode 100644 playfab-docs/api-references/events/player-inventory-item-added.md delete mode 100644 playfab-docs/api-references/events/player-paid-for-purchase.md delete mode 100644 playfab-docs/api-references/events/player-realmoney-purchase.md delete mode 100644 playfab-docs/api-references/events/player-receipt-validation.md delete mode 100644 playfab-docs/api-references/events/player-redeemed-coupon.md delete mode 100644 playfab-docs/api-references/events/player-started-purchase.md delete mode 100644 playfab-docs/api-references/events/player-vc-item-purchased.md delete mode 100644 playfab-docs/api-references/events/player-virtual-currency-balance-changed.md delete mode 100644 playfab-docs/api-references/events/review-reported.md delete mode 100644 playfab-docs/api-references/events/title-store-updated.md diff --git a/playfab-docs/api-references/events/title-catalog-updated.md b/playfab-docs/api-references/events/CatalogV1/title-catalog-updated.md similarity index 53% rename from playfab-docs/api-references/events/title-catalog-updated.md rename to playfab-docs/api-references/events/CatalogV1/title-catalog-updated.md index f6104f133..2723f0881 100644 --- a/playfab-docs/api-references/events/title-catalog-updated.md +++ b/playfab-docs/api-references/events/CatalogV1/title-catalog-updated.md @@ -16,13 +16,13 @@ This event is triggered when a catalog is changed. ## Properties -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CatalogVersion|String|Version of the catalog that was updated.| -|Deleted|Boolean|Was the catalog deleted.| -|DeveloperId|String|| -|UserId|String|| +| Name | Type | Description | +| :--- | :--- | :--- | +| CatalogVersion | String | Version of the catalog that was updated. | +| Deleted | Boolean | Was the catalog deleted. | +| DeveloperId | String | | +| UserId | String | | ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/CatalogV1/title-store-updated.md b/playfab-docs/api-references/events/CatalogV1/title-store-updated.md new file mode 100644 index 000000000..64c101858 --- /dev/null +++ b/playfab-docs/api-references/events/CatalogV1/title-store-updated.md @@ -0,0 +1,29 @@ +--- +title: title_store_updated +author: ernestoc +description: title_store_updated event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# title_store_updated + +This event is triggered when a store is changed. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CatalogVersion | String | Catalog version that the updated store belongs to. | +| Deleted | Boolean | Was the store deleted. | +| DeveloperId | String | | +| StoreId | String | ID of the updated store. | +| UserId | String | | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/CatalogV2/item-created.md b/playfab-docs/api-references/events/CatalogV2/item-created.md new file mode 100644 index 000000000..824c1fe32 --- /dev/null +++ b/playfab-docs/api-references/events/CatalogV2/item-created.md @@ -0,0 +1,26 @@ +--- +title: item_created +author: ernestoc +description: ItemCreated event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# item_created + +This event is triggered when an item is created. + +## Properties + +| Name | Type | Description | +| :------- | :----- | :-------------------------------------------- | +| ItemId | String | The string of the item that was created. | +| ItemType | String | The string type of the item that was created. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/CatalogV2/item-deleted.md b/playfab-docs/api-references/events/CatalogV2/item-deleted.md new file mode 100644 index 000000000..fd61676b3 --- /dev/null +++ b/playfab-docs/api-references/events/CatalogV2/item-deleted.md @@ -0,0 +1,26 @@ +--- +title: item_deleted +author: ernestoc +description: ItemDeleted event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# item_deleted + +This event is triggered when an item is deleted. + +## Properties + +| Name | Type | Description | +| :------- | :----- | :-------------------------------------------- | +| ItemId | String | The string ID of the item that was deleted. | +| ItemType | String | The string type of the item that was deleted. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/item-moderation-state-changed.md b/playfab-docs/api-references/events/CatalogV2/item-moderation-state-changed.md similarity index 51% rename from playfab-docs/api-references/events/item-moderation-state-changed.md rename to playfab-docs/api-references/events/CatalogV2/item-moderation-state-changed.md index 8ad7dc5ab..52ebb4501 100644 --- a/playfab-docs/api-references/events/item-moderation-state-changed.md +++ b/playfab-docs/api-references/events/CatalogV2/item-moderation-state-changed.md @@ -16,12 +16,12 @@ This event is triggered when an item moderation state is changed. ## Properties -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|ItemId|String|The string ID of the item whos state was changed.| -|TargetStatus|String|The updated moderation status of the item.| -|Reason|String|The current stated reason for the associated item being moderated.| +| Name | Type | Description | +| :--- | :--- | :--- | +| ItemId | String | The string ID of the item whos state was changed. | +| TargetStatus | String | The updated moderation status of the item. | +| Reason | String | The current stated reason for the associated item being moderated. | ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/item-publish-requested.md b/playfab-docs/api-references/events/CatalogV2/item-publish-requested.md similarity index 54% rename from playfab-docs/api-references/events/item-publish-requested.md rename to playfab-docs/api-references/events/CatalogV2/item-publish-requested.md index 1e4374fb3..5251a95d5 100644 --- a/playfab-docs/api-references/events/item-publish-requested.md +++ b/playfab-docs/api-references/events/CatalogV2/item-publish-requested.md @@ -16,11 +16,11 @@ This event is triggered when an publishing is started. ## Properties -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|ItemId|String|The string ID of the item that is to be published.| -|ItemType|String|The string type of the item that is to be published.| +| Name | Type | Description | +| :--- | :--- | :--- | +| ItemId | String | The string ID of the item that is to be published. | +| ItemType | String | The string type of the item that is to be published. | ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] \ No newline at end of file +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/CatalogV2/item-purchased.md b/playfab-docs/api-references/events/CatalogV2/item-purchased.md new file mode 100644 index 000000000..329f9cc46 --- /dev/null +++ b/playfab-docs/api-references/events/CatalogV2/item-purchased.md @@ -0,0 +1,37 @@ +--- +title: item_purchased +author: ernestoc +description: item_purchased event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# item_purchased + +This event is triggered when an item is purchased. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CollectionId | String | The id of the collection the item was added to. | +| Currencies | List<[ItemPurchasedCurrency](../data-types/itempurchasedcurrency.md)> | The set of currencies used to pay for the item. | +| IdempotencyId | String | The idempotency id. | +| ItemId | String | The id of the purchased item. | +| ItemsAmountsOverrides | List<[ItemPurchasedOverride](../data-types/itempurchasedoverride.md)> | The set of overrides used to alter item amounts. | +| ItemType | String | The type of the purchased item. | +| OverrideSource | String | The source of the overrides used in the purchase. | +| PayoutAmountOverride | [ItemPurchasedOverride](../data-types/itempurchasedoverride.md) | The override used to alter the payout of the purchase. | +| PriceAmountsOverrides | List<[ItemPurchasedOverride](../data-types/itempurchasedoverride.md)> | The set of overrides used to alter the price in the purchase. | +| Quantity | uint64 | The quantity of purchased items. | +| StoreId | String | The optional id of the store. | +| TransactionDateTime | String | Timestamp of the transaction in ISO-8601 format. | +| TransactionId | String | The id of the transaction which added this item. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/CatalogV2/item-reported.md b/playfab-docs/api-references/events/CatalogV2/item-reported.md new file mode 100644 index 000000000..07b2750ae --- /dev/null +++ b/playfab-docs/api-references/events/CatalogV2/item-reported.md @@ -0,0 +1,29 @@ +--- +title: item_reported +author: ernestoc +description: ItemReported event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# item_reported + +This event is triggered when an item is reported. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| ItemId | String | The string ID of the item that was reported. | +| ItemType | String | The string type of the item that was reported. | +| CreatorEntityKey | [EntityKey](../data-types/entitykey.md) | The item's creator. | +| ConcernCategory | String | The category for which this item was reported. | +| Reason | String | The reason for which this item was reported. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/item-updated.md b/playfab-docs/api-references/events/CatalogV2/item-updated.md similarity index 53% rename from playfab-docs/api-references/events/item-updated.md rename to playfab-docs/api-references/events/CatalogV2/item-updated.md index 36f7bd178..2e1c8c64b 100644 --- a/playfab-docs/api-references/events/item-updated.md +++ b/playfab-docs/api-references/events/CatalogV2/item-updated.md @@ -16,11 +16,11 @@ This event is triggered when an item is updated. ## Properties -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|ItemId|String|The string ID of the item that was updated.| -|ItemType|String|The string type of the item that was updated.| +| Name | Type | Description | +| :--- | :--- | :--- | +| ItemId | String | The string ID of the item that was updated. | +| ItemType | String | The string type of the item that was updated. | ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/CatalogV2/review-reported.md b/playfab-docs/api-references/events/CatalogV2/review-reported.md new file mode 100644 index 000000000..1c5f1ecba --- /dev/null +++ b/playfab-docs/api-references/events/CatalogV2/review-reported.md @@ -0,0 +1,29 @@ +--- +title: review_reported +author: ernestoc +description: ReviewReported event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# review_reported + +This event is triggered when a review is reported. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| ItemId | String | The string ID of the item associated with the review. | +| ReviewId | String | The string ID of the review being reported. | +| ConcernCategory | String | The category for which this review was reported. | +| Reason | String | The string reason for this report. | +| CreatorEntityKey | [EntityKey](../data-types/entitykey.md) | The EntityKey of the creator of the review that was reported. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/reviews-takedown-requested.md b/playfab-docs/api-references/events/CatalogV2/reviews-takedown-requested.md similarity index 59% rename from playfab-docs/api-references/events/reviews-takedown-requested.md rename to playfab-docs/api-references/events/CatalogV2/reviews-takedown-requested.md index bf59b245f..37ce51c63 100644 --- a/playfab-docs/api-references/events/reviews-takedown-requested.md +++ b/playfab-docs/api-references/events/CatalogV2/reviews-takedown-requested.md @@ -16,10 +16,10 @@ Event trigged when a takedown of reviews is requested. ## Properties -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|Reviews|List<[ReviewTakedown](data-types/review-takedown.md)>|The reviews to be taken down.| +| Name | Type | Description | +| :--- | :--- | :--- | +| Reviews | List<[ReviewTakedown](../data-types/review-takedown.md)> | The reviews to be taken down. | ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/character-consumed-item.md b/playfab-docs/api-references/events/InventoryV1/character-consumed-item.md new file mode 100644 index 000000000..7c05b5185 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/character-consumed-item.md @@ -0,0 +1,31 @@ +--- +title: character_consumed_item +author: ernestoc +description: character_consumed_item event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# character_consumed_item + +This event is triggered when a character consumes an item from their inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CatalogVersion | String | Version of the catalog from which the consumed inventory item was created. | +| ItemId | String | ID of the catalog item from which the consumed inventory item was created. This can be used to look up the item from the catalog. | +| ItemInstanceId | String | The specific ID of the item that was consumed. | +| PlayerId | String | | +| PreviousUsesRemaining | uint32 | For multiple use items, the number of uses that remained before the item was consumed. | +| TitleId | String | | +| UsesRemaining | uint32 | For multiple use items, the number of uses remaining after the item was consumed. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/character-inventory-item-added.md b/playfab-docs/api-references/events/InventoryV1/character-inventory-item-added.md new file mode 100644 index 000000000..00accff65 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/character-inventory-item-added.md @@ -0,0 +1,36 @@ +--- +title: character_inventory_item_added +author: ernestoc +description: character_inventory_item_added event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# character_inventory_item_added + +This event is triggered when an item is granted to a character. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| Annotation | String | Optional details about the inventory item. | +| BundleContents | [] | Catalog item IDs of any other items granted to the character along with this one as part of a bundle. | +| CatalogVersion | String | Catalog version in which the item that was added is defined. | +| Class | String | Class of the item that was added. | +| CouponCode | String | Redeemed coupon (if any) that granted the item. | +| DisplayName | String | Display name of the item that was added. | +| Expiration | DateTime | When the item expires. The value is null if the item does not expire. | +| InstanceId | String | Unique instance ID of the inventory item that was added. | +| ItemId | String | Catalog item ID of the inventory item that was added. | +| PlayerId | String | | +| RemainingUses | uint32 | How many uses the item has, if it has a limited number of uses. | +| TitleId | String | | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/character-vc-item-purchased.md b/playfab-docs/api-references/events/InventoryV1/character-vc-item-purchased.md new file mode 100644 index 000000000..7a60cfa50 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/character-vc-item-purchased.md @@ -0,0 +1,33 @@ +--- +title: character_vc_item_purchased +author: ernestoc +description: character_vc_item_purchased event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# character_vc_item_purchased + +This event is triggered when the character makes a purchase using virtual currency. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CatalogVersion | String | Version of the catalog from which the item was purchased. | +| CurrencyCode | String | Currency that was used to purchase the item. | +| ItemId | String | Identifier of the catalog item that was purchased. | +| PlayerId | String | | +| PurchaseId | String | Unique identifier of the purchase transaction. | +| Quantity | int32 | Quantity of items that were purchased. | +| StoreId | String | The StoreId where the item was purchased. | +| TitleId | String | | +| UnitPrice | uint32 | Price paid per item, expressed in the virtual currency. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/character-virtual-currency-balance-changed.md b/playfab-docs/api-references/events/InventoryV1/character-virtual-currency-balance-changed.md new file mode 100644 index 000000000..17935b139 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/character-virtual-currency-balance-changed.md @@ -0,0 +1,30 @@ +--- +title: character_virtual_currency_balance_changed +author: ernestoc +description: character_virtual_currency_balance_changed event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# character_virtual_currency_balance_changed + +This event is triggered when a character's virtual currency balance changes. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| OrderId | String | ID of the order that triggered the balance changes. | +| PlayerId | String | | +| TitleId | String | | +| VirtualCurrencyBalance | int32 | New virtual currency balance after the change. | +| VirtualCurrencyName | String | Virtual currency whose balance changed. | +| VirtualCurrencyPreviousBalance | int32 | Old virtual currency balance before the change. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-consumed-item.md b/playfab-docs/api-references/events/InventoryV1/player-consumed-item.md new file mode 100644 index 000000000..177165e65 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/player-consumed-item.md @@ -0,0 +1,30 @@ +--- +title: player_consumed_item +author: ernestoc +description: player_consumed_item event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_consumed_item + +This event is triggered when a player consumes an item from their inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CatalogVersion | String | Version of the catalog from which the consumed inventory item was created. | +| ItemId | String | ID of the catalog item from which the consumed inventory item was created. This can be used to look up the item from the catalog. | +| ItemInstanceId | String | The specific ID of the item that was consumed. | +| PreviousUsesRemaining | uint32 | For multiple use items, the number of uses that remained before the item was consumed. | +| TitleId | String | The ID of the title to which this player event applies. | +| UsesRemaining | uint32 | For multiple use items, the number of uses remaining after the item was consumed. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-inventory-item-added.md b/playfab-docs/api-references/events/InventoryV1/player-inventory-item-added.md new file mode 100644 index 000000000..caf7ac919 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/player-inventory-item-added.md @@ -0,0 +1,35 @@ +--- +title: player_inventory_item_added +author: ernestoc +description: player_inventory_item_added event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_inventory_item_added + +This event is triggered when an item is granted to a player. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| Annotation | String | Optional details about the inventory item. | +| BundleContents | [] | Catalog item IDs of any other items granted to the player along with this one as part of a bundle. | +| CatalogVersion | String | Catalog version in which the item that was added is defined. | +| Class | String | Class of the item that was added. | +| CouponCode | String | Redeemed coupon (if any) that granted the item. | +| DisplayName | String | Display name of the item that was added. | +| Expiration | DateTime | When the item expires. The value is null if the item does not expire. | +| InstanceId | String | Unique instance ID of the inventory item that was added. | +| ItemId | String | Catalog item ID of the inventory item that was added. | +| RemainingUses | uint32 | How many uses the item has, if it has a limited number of uses. | +| TitleId | String | The ID of the title to which this player event applies. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-paid-for-purchase.md b/playfab-docs/api-references/events/InventoryV1/player-paid-for-purchase.md new file mode 100644 index 000000000..159bd5b68 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/player-paid-for-purchase.md @@ -0,0 +1,35 @@ +--- +title: player_paid_for_purchase +author: ernestoc +description: player_paid_for_purchase event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_paid_for_purchase + +This event is triggered when the second step of the payment process completes, paying for the purchase. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| OrderId | String | Purchase order identifier. | +| ProviderData | String | Provider used for the transaction. | +| ProviderName | String | Payment provider to use to fund the purchase. | +| ProviderToken | String | A token generated by the provider to authenticate the request (provider-specific). | +| PurchaseConfirmationPageURL | String | URL to the purchase provider page that details the purchase. | +| PurchaseCurrency | String | Currency for the transaction, may be a virtual currency or real money. | +| PurchasePrice | uint32 | Cost of the transaction. | +| Status | [TransactionStatus](../data-types/transactionstatus.md) | Status of the transaction. | +| TitleId | String | The ID of the title to which this player event applies. | +| VirtualCurrencyBalances | Object | Current virtual currency balances for the user. | +| VirtualCurrencyGrants | Object | Virtual currencies granted by the transaction, if any. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-realmoney-purchase.md b/playfab-docs/api-references/events/InventoryV1/player-realmoney-purchase.md new file mode 100644 index 000000000..496b4a8db --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/player-realmoney-purchase.md @@ -0,0 +1,33 @@ +--- +title: player_realmoney_purchase +author: ernestoc +description: player_realmoney_purchase event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_realmoney_purchase + +This event is triggered when a player makes a real money purchase, and generates revenue for the game. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| OrderId | String | Unique identifier of the order. | +| OrderTotal | uint32 | Total value of the purchase in the system currency (defaults to USD). | +| PaymentProvider | String | Payment provider used to make the purchase. | +| PaymentType | [PaymentType](../data-types/paymenttype.md) | Type of payment used to make the purchase. | +| PurchasedProduct | [] | The ItemIds from the catalog of the purchased items, if applicable. | +| TitleId | String | The ID of the title to which this player event applies. | +| TransactionCurrency | [Currency](../data-types/currency.md) | Local currency used to make the purchase, if applicable. | +| TransactionId | String | Unique identifier of the transaction. | +| TransactionTotal | uint32 | Total value of the purchase in the local currency used to make the purchase, if applicable. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-receipt-validation.md b/playfab-docs/api-references/events/InventoryV1/player-receipt-validation.md new file mode 100644 index 000000000..51900258d --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/player-receipt-validation.md @@ -0,0 +1,30 @@ +--- +title: player_receipt_validation +author: ernestoc +description: player_receipt_validation event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_receipt_validation + +This event is triggered when a player attempts to make a real money purchase and the purchase receipt is being validated. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| Error | String | The error that occurred during a receipt validation. | +| PaymentProvider | String | Payment provider used to make the purchase attempt. | +| PaymentType | [PaymentType](../data-types/paymenttype.md) | Type of payment used to make the purchase attempt. | +| ReceiptContent | String | The receipt data during a real money purchase event attempt. | +| TitleId | String | The ID of the title to which this player event applies. | +| Valid | Boolean | Indicates if the receipt is valid. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-redeemed-coupon.md b/playfab-docs/api-references/events/InventoryV1/player-redeemed-coupon.md new file mode 100644 index 000000000..57019e80a --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/player-redeemed-coupon.md @@ -0,0 +1,27 @@ +--- +title: player_redeemed_coupon +author: ernestoc +description: player_redeemed_coupon event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_redeemed_coupon + +This event is triggered when a player redeems a coupon. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CouponCode | String | Coupon code the player redeemed. | +| GrantedInventoryItems | [CouponGrantedInventoryItem](../data-types/coupongrantedinventoryitem.md) | Items added to the player's inventory by redeeming the coupon. | +| TitleId | String | The ID of the title to which this player event applies. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-started-purchase.md b/playfab-docs/api-references/events/InventoryV1/player-started-purchase.md new file mode 100644 index 000000000..7ae855413 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/player-started-purchase.md @@ -0,0 +1,29 @@ +--- +title: player_started_purchase +author: ernestoc +description: player_started_purchase event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_started_purchase + +This event is triggered when a player starts a purchase. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CatalogVersion | String | Catalog version for the items to be purchased. Defaults to most recent catalog. | +| Contents | [CartItem](../data-types/cartitem.md) | Cart items to be purchased. | +| OrderId | String | Purchase order identifier. | +| StoreId | String | Store through which to purchase items. If not set, prices will be pulled from the catalog itself. | +| TitleId | String | The ID of the title to which this player event applies. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-vc-item-purchased.md b/playfab-docs/api-references/events/InventoryV1/player-vc-item-purchased.md new file mode 100644 index 000000000..33cc2f3ec --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/player-vc-item-purchased.md @@ -0,0 +1,32 @@ +--- +title: player_vc_item_purchased +author: ernestoc +description: player_vc_item_purchased event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_vc_item_purchased + +This event is triggered when the player makes a purchase using virtual currency. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CatalogVersion | String | Version of the catalog from which the item was purchased. | +| CurrencyCode | String | Currency that was used to purchase the item. | +| ItemId | String | Identifier of the catalog item that was purchased. | +| PurchaseId | String | Unique identifier of the purchase transaction. | +| Quantity | int32 | Quantity of items that were purchased. | +| StoreId | String | The StoreId where the item was purchased. | +| TitleId | String | The ID of the title to which this player event applies. | +| UnitPrice | uint32 | Price paid per item, expressed in the virtual currency. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-virtual-currency-balance-changed.md b/playfab-docs/api-references/events/InventoryV1/player-virtual-currency-balance-changed.md new file mode 100644 index 000000000..dc0d14f2f --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV1/player-virtual-currency-balance-changed.md @@ -0,0 +1,29 @@ +--- +title: player_virtual_currency_balance_changed +author: ernestoc +description: player_virtual_currency_balance_changed event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_virtual_currency_balance_changed + +This event is triggered when a player's virtual currency balance changes. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| OrderId | String | Id of the order that triggered the balance changes | +| TitleId | String | The ID of the title to which this player event applies. | +| VirtualCurrencyBalance | int32 | New virtual currency balance after the change. | +| VirtualCurrencyName | String | Virtual currency whose balance changed. | +| VirtualCurrencyPreviousBalance | int32 | Old virtual currency balance before the change. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-added.md b/playfab-docs/api-references/events/InventoryV2/items-added.md new file mode 100644 index 000000000..07fbedefd --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-added.md @@ -0,0 +1,32 @@ +--- +title: items_added +author: ernestoc +description: ItemsAdded event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_added + +Event raised when items have been added to an inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| TransactionId | String | The transaction id. | +| CollectionId | String | The collection id. | +| ItemId | String | The item id. | +| StackId | String | The stack id. | +| Amount | int? | The amount of items that were added. | +| DurationInSeconds | long? | The duration of the item that was added. | +| ItemType | String | The type of the catalog item that was modified in the transaction. | +| Balance | int? | The balance of the items changed as a result of the transaction. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-clawback-completed.md b/playfab-docs/api-references/events/InventoryV2/items-clawback-completed.md new file mode 100644 index 000000000..07d769e2c --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-clawback-completed.md @@ -0,0 +1,29 @@ +--- +title: items_clawback_completed +author: ernestoc +description: items_clawback_completed event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_clawback_completed + +This event is triggered when an items clawback operation is completed. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| EntityLineage | [EntityLineage](../data-types/entitylineage.md) | Entities that this entity is a child of. | +| OriginalEventId | String | The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server. | +| OriginalTimestamp | DateTime | The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server. | +| Payload | [ItemsClawbackCompletedPayload](../data-types/itemsclawbackcompletedpayload.md) | The items clawback completed event payload. | +| WriterEntity | [EntityKey](../data-types/entitykey.md) | Entity that wrote this event, included only if different than the event's entity. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-clawback-reversal-completed.md b/playfab-docs/api-references/events/InventoryV2/items-clawback-reversal-completed.md new file mode 100644 index 000000000..406dc1ef0 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-clawback-reversal-completed.md @@ -0,0 +1,29 @@ +--- +title: items_clawback_reversal_completed +author: ernestoc +description: items_clawback_reversal_completed event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_clawback_reversal_completed + +This event is triggered when an items clawback reversal operation is completed. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| EntityLineage | [EntityLineage](../data-types/entitylineage.md) | Entities that this entity is a child of. | +| OriginalEventId | String | The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server. | +| OriginalTimestamp | DateTime | The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server. | +| Payload | [ItemsClawbackReversalCompletedPayload](../data-types/itemsclawbackreversalcompletedpayload.md) | The items clawback reversal completed event payload. | +| WriterEntity | [EntityKey](../data-types/entitykey.md) | Entity that wrote this event, included only if different than the event's entity. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-deleted.md b/playfab-docs/api-references/events/InventoryV2/items-deleted.md new file mode 100644 index 000000000..10137d99e --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-deleted.md @@ -0,0 +1,29 @@ +--- +title: items_deleted +author: ernestoc +description: ItemsDeleted event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_deleted + +Event raised when items have been deleted from an inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| TransactionId | String | The transaction id. | +| CollectionId | String | The collection id. | +| ItemId | String | The item id. | +| StackId | String | The stack id. | +| ItemType | String | The type of the catalog item that was modified in the transaction. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-expired.md b/playfab-docs/api-references/events/InventoryV2/items-expired.md new file mode 100644 index 000000000..38cb15e38 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-expired.md @@ -0,0 +1,29 @@ +--- +title: items_expired +author: ernestoc +description: items_expired event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_expired + +This event is triggered when items have expired in an inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| EntityLineage | [EntityLineage](../data-types/entitylineage.md) | Entities that this entity is a child of. | +| OriginalEventId | String | The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server. | +| OriginalTimestamp | DateTime | The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server. | +| Payload | [ItemsExpiredPayload](../data-types/itemsexpiredpayload.md) | The items expired event payload. | +| WriterEntity | [EntityKey](../data-types/entitykey.md) | Entity that wrote this event, included only if different than the event's entity. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-purchased.md b/playfab-docs/api-references/events/InventoryV2/items-purchased.md new file mode 100644 index 000000000..c4f2b8d7b --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-purchased.md @@ -0,0 +1,34 @@ +--- +title: items_purchased +author: ernestoc +description: ItemsPurchased event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_purchased + +Event raised when items have been purchased from an inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| TransactionId | String | The transaction id. | +| CollectionId | String | The collection id. | +| ItemId | String | The item id. | +| StackId | String | The stack id. | +| Amount | int? | The amount of items that were puchased. | +| DurationInSeconds | long? | The duration of the item that was purchased. | +| SalePriceAmounts | List<[PurchasePriceAmount](../data-types/purchasepriceamount.md)> | The per-item price amounts the item was purchased at. | +| StoreId | String | The id of the Store the item was purchased from or null. | +| ItemType | String | The type of the catalog item that was modified in the transaction. | +| Balance | int? | The balance of the items changed as a result of the transaction. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-redeemed.md b/playfab-docs/api-references/events/InventoryV2/items-redeemed.md new file mode 100644 index 000000000..b79573595 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-redeemed.md @@ -0,0 +1,34 @@ +--- +title: items_redeemed +author: ernestoc +description: ItemsRedeemed event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_redeemed + +Event raised when items have been redeemed to an inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| TransactionId | String | The transaction id. | +| CollectionId | String | The collection id. | +| ItemId | String | The item id. | +| StackId | String | The stack id. | +| Amount | int? | The amount of items that were redeemed. | +| DurationInSeconds | long? | The duration of the item that was redeemed. | +| Marketplace | String | The name of the marketplace that the items were redeemed from. | +| MarketplaceTransactionId | String | The transaction id in the marketplace that the items were redeemed from. | +| ItemType | String | The type of the catalog item that was modified in the transaction. | +| Balance | int? | The balance of the items changed as a result of the transaction. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-subtracted.md b/playfab-docs/api-references/events/InventoryV2/items-subtracted.md new file mode 100644 index 000000000..0e4cd05eb --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-subtracted.md @@ -0,0 +1,32 @@ +--- +title: items_subtracted +author: ernestoc +description: ItemsSubtracted event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_subtracted + +Event raised when items have been subtracted from an inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| TransactionId | String | The transaction id. | +| CollectionId | String | The collection id. | +| ItemId | String | The item id. | +| StackId | String | The stack id. | +| Amount | int? | The amount of items that were subtracted. | +| DurationInSeconds | long? | The duration of the item that was subtracted. | +| ItemType | String | The type of the catalog item that was modified in the transaction. | +| Balance | int? | The balance of the items changed as a result of the transaction. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-transferred.md b/playfab-docs/api-references/events/InventoryV2/items-transferred.md new file mode 100644 index 000000000..701dcabac --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-transferred.md @@ -0,0 +1,36 @@ +--- +title: items_transferred +author: ernestoc +description: ItemsTransferred event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_transferred + +Event raised when items have been transferred to or from an inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| TransactionId | String | The transaction id. | +| CollectionId | String | The collection id. | +| ItemId | String | The item id. | +| StackId | String | The stack id. | +| Amount | int? | The amount of items that were transferred. | +| DurationInSeconds | long? | The duration of the item that was transferred. | +| GivingEntity | [EntityKey](../data-types/entitykey.md)? | The entity the items were transferred from or null if it was the current entity. | +| ReceivingEntity | [EntityKey](../data-types/entitykey.md)? | The entity the items were transferred to or null if it was the current entity. | +| GivingCollectionId | String | The collection if the items were transferred from or null if it was the current collection. | +| ReceivingCollectionId | String | The collection id the items were transferred to or null if it was the current collection. | +| ItemType | String | The type of the catalog item that was modified in the transaction. | +| Balance | int? | The balance of the items changed as a result of the transaction. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-updated.md b/playfab-docs/api-references/events/InventoryV2/items-updated.md new file mode 100644 index 000000000..7b91f8d08 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/items-updated.md @@ -0,0 +1,31 @@ +--- +title: items_updated +author: ernestoc +description: ItemsUpdated event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# items_updated + +Event raised when items have been updated in an inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| TransactionId | String | The transaction id. | +| CollectionId | String | The collection id. | +| ItemId | String | The item id. | +| StackId | String | The stack id. | +| Amount | int? | The amount of item. | +| Expiration | String | The date the item expires. | +| ItemType | String | The type of the catalog item that was modified in the transaction. | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/marketplace-transaction-redeemed.md b/playfab-docs/api-references/events/InventoryV2/marketplace-transaction-redeemed.md new file mode 100644 index 000000000..4a0c91967 --- /dev/null +++ b/playfab-docs/api-references/events/InventoryV2/marketplace-transaction-redeemed.md @@ -0,0 +1,32 @@ +--- +title: marketplace_transaction_redeemed +author: ernestoc +description: marketplace_transaction_redeemed event. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# marketplace_transaction_redeemed + +This event is triggered when a bundle or subscription has been redeemed to an inventory. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| Marketplace | String | The name of the marketplace the items were redeemed from. | +| MarketplaceTransctionId | String | The transaction Id from the marketplace the items were redeemed from. | +| MarketplaceAlternateId | String | The alternate Id of the item for the marketplace. | +| Amount | int? | The amount that was redeemed. | +| DurationInSeconds | long? | The amount of subscription that was redeemed. | +| ItemId | String | The identifier of the item that was redeemed. | +| ItemType | String | The type of the catalog item that was redeemed. | +| RealMoneyPrices | Dictionary | The multi-currency unit price, in real money, of the item that was redeemed. The property is a dictionary where the key is the three-letter currency code as defined in ISO 4217, and the value is the currency amount in the smallest unit (for example, cents, pence) in accordance with ISO 4217. Only United States Dollar (USD) is currently supported. Example: If the product price in USD is $1.39, the dictionary entry would be: ["USD"] = 139; | + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/character-consumed-item.md b/playfab-docs/api-references/events/character-consumed-item.md deleted file mode 100644 index 88ee4d266..000000000 --- a/playfab-docs/api-references/events/character-consumed-item.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: character_consumed_item -author: joannaleecy -description: character_consumed_item event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# character_consumed_item - -This event is triggered when a character consumes an item from their inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CatalogVersion|String|Version of the catalog from which the consumed inventory item was created.| -|ItemId|String|ID of the catalog item from which the consumed inventory item was created. This can be used to look up the item from the catalog.| -|ItemInstanceId|String|The specific ID of the item that was consumed.| -|PlayerId|String|| -|PreviousUsesRemaining|uint32|For multiple use items, the number of uses that remained before the item was consumed.| -|TitleId|String|| -|UsesRemaining|uint32|For multiple use items, the number of uses remaining after the item was consumed.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-inventory-item-added.md b/playfab-docs/api-references/events/character-inventory-item-added.md deleted file mode 100644 index cd36929d2..000000000 --- a/playfab-docs/api-references/events/character-inventory-item-added.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: character_inventory_item_added -author: joannaleecy -description: character_inventory_item_added event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# character_inventory_item_added - -This event is triggered when an item is granted to a character. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|Annotation|String|Optional details about the inventory item.| -|BundleContents|[]|Catalog item IDs of any other items granted to the character along with this one as part of a bundle.| -|CatalogVersion|String|Catalog version in which the item that was added is defined.| -|Class|String|Class of the item that was added.| -|CouponCode|String|Redeemed coupon (if any) that granted the item.| -|DisplayName|String|Display name of the item that was added.| -|Expiration|DateTime|When the item expires. The value is null if the item does not expire.| -|InstanceId|String|Unique instance ID of the inventory item that was added.| -|ItemId|String|Catalog item ID of the inventory item that was added.| -|PlayerId|String|| -|RemainingUses|uint32|How many uses the item has, if it has a limited number of uses.| -|TitleId|String|| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-vc-item-purchased.md b/playfab-docs/api-references/events/character-vc-item-purchased.md deleted file mode 100644 index fd58520c1..000000000 --- a/playfab-docs/api-references/events/character-vc-item-purchased.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: character_vc_item_purchased -author: joannaleecy -description: character_vc_item_purchased event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# character_vc_item_purchased - -This event is triggered when the character makes a purchase using virtual currency. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CatalogVersion|String|Version of the catalog from which the item was purchased.| -|CurrencyCode|String|Currency that was used to purchase the item.| -|ItemId|String|Identifier of the catalog item that was purchased.| -|PlayerId|String|| -|PurchaseId|String|Unique identifier of the purchase transaction.| -|Quantity|int32|Quantity of items that were purchased.| -|StoreId|String|The StoreId where the item was purchased.| -|TitleId|String|| -|UnitPrice|uint32|Price paid per item, expressed in the virtual currency.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/character-virtual-currency-balance-changed.md b/playfab-docs/api-references/events/character-virtual-currency-balance-changed.md deleted file mode 100644 index 26922799c..000000000 --- a/playfab-docs/api-references/events/character-virtual-currency-balance-changed.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: character_virtual_currency_balance_changed -author: joannaleecy -description: character_virtual_currency_balance_changed event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# character_virtual_currency_balance_changed - -This event is triggered when a character's virtual currency balance changes. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|OrderId|String|ID of the order that triggered the balance changes.| -|PlayerId|String|| -|TitleId|String|| -|VirtualCurrencyBalance|int32|New virtual currency balance after the change.| -|VirtualCurrencyName|String|Virtual currency whose balance changed.| -|VirtualCurrencyPreviousBalance|int32|Old virtual currency balance before the change.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/data-types/itempurchasedcurrency.md b/playfab-docs/api-references/events/data-types/itempurchasedcurrency.md new file mode 100644 index 000000000..a68ad922c --- /dev/null +++ b/playfab-docs/api-references/events/data-types/itempurchasedcurrency.md @@ -0,0 +1,22 @@ +--- +title: ItemPurchasedCurrency +author: ernestoc +description: ItemPurchasedCurrency data type. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ItemPurchasedCurrency + +Represents a currency used during a purchase event. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CurrencyId | String | The id of the currency. | +| Quantity | uint64 | The quantity of the currency. | diff --git a/playfab-docs/api-references/events/data-types/itempurchasedoverride.md b/playfab-docs/api-references/events/data-types/itempurchasedoverride.md new file mode 100644 index 000000000..a5ada8405 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/itempurchasedoverride.md @@ -0,0 +1,23 @@ +--- +title: ItemPurchasedOverride +author: ernestoc +description: ItemPurchasedOverride data type. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ItemPurchasedOverride + +Represents an override used during a purchase event. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| FixedValue | double | The fixed value of the override. | +| ItemId | String | The id of the item. | +| Multiplier | double | The multiplier of the override. | diff --git a/playfab-docs/api-references/events/data-types/itemsclawbackcompletedpayload.md b/playfab-docs/api-references/events/data-types/itemsclawbackcompletedpayload.md new file mode 100644 index 000000000..211e379bf --- /dev/null +++ b/playfab-docs/api-references/events/data-types/itemsclawbackcompletedpayload.md @@ -0,0 +1,32 @@ +--- +title: ItemsClawbackCompletedPayload +author: ernestoc +description: ItemsClawbackCompletedPayload data type. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ItemsClawbackCompletedPayload + +Items clawback completed event payload. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| Amount | int | The amount of items that were clawed back. | +| Balance | int | The balance of the item after the transaction. | +| CollectionId | String | The collection ID the item was clawed back from. | +| ItemId | String | The ID of the item that was clawed back. | +| ItemType | String | The type of the catalog item that was clawed back. | +| Marketplace | String | The name of the marketplace the items were clawed back from. | +| MarketplaceAlternateId | String | The alternate ID of the item for the marketplace. | +| MarketplaceEventId | String | The event ID from the marketplace that triggered this clawback. | +| MarketplaceTransactionId | String | The ID of the marketplace transaction. | +| RedemptionDetails | RedemptionDetails | The details of the original redeem operation. | +| StackId | String | The stack ID that the item was clawed back from. | +| TransactionId | String | ID of the transaction which clawed back this item. | diff --git a/playfab-docs/api-references/events/data-types/itemsclawbackreversalcompletedpayload.md b/playfab-docs/api-references/events/data-types/itemsclawbackreversalcompletedpayload.md new file mode 100644 index 000000000..e1ad5c9ba --- /dev/null +++ b/playfab-docs/api-references/events/data-types/itemsclawbackreversalcompletedpayload.md @@ -0,0 +1,32 @@ +--- +title: ItemsClawbackReversalCompletedPayload +author: ernestoc +description: ItemsClawbackReversalCompletedPayload data type. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ItemsClawbackReversalCompletedPayload + +Items clawback reversal completed event payload. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| Amount | int | The amount of items that were added. | +| Balance | int | The balance of the item after the transaction. | +| ClawbackDetails | ClawbackDetails | The details of the original clawback operation. | +| CollectionId | String | The collection ID the item was added to. | +| ItemId | String | The ID of the item that was added. | +| ItemType | String | The type of the catalog item. | +| Marketplace | String | The name of the marketplace that triggered this clawback reversal. | +| MarketplaceAlternateId | String | The alternate ID of the item for the marketplace. | +| MarketplaceEventId | String | The event ID from the marketplace that triggered this clawback reversal. | +| MarketplaceTransactionId | String | The ID of the marketplace transaction. | +| StackId | String | The stack ID that the item was added to. | +| TransactionId | String | ID of the transaction which performed a clawback reversal on this item. | diff --git a/playfab-docs/api-references/events/data-types/itemsexpiredpayload.md b/playfab-docs/api-references/events/data-types/itemsexpiredpayload.md new file mode 100644 index 000000000..5d10f586d --- /dev/null +++ b/playfab-docs/api-references/events/data-types/itemsexpiredpayload.md @@ -0,0 +1,27 @@ +--- +title: ItemsExpiredPayload +author: ernestoc +description: ItemsExpiredPayload data type. +ms.author: ernestoc +ms.date: 02/18/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ItemsExpiredPayload + +Items expired event payload. + +## Properties + +| Name | Type | Description | +| :--- | :--- | :--- | +| CollectionId | String | The collection ID. | +| ExpirationDate | String | The expiration date in ISO-8601 format. | +| ItemId | String | The item ID. | +| ItemType | String | The type of the catalog item that was modified. | +| StackId | String | The stack ID. | +| StartDate | String | The start date in ISO-8601 format. | +| TransactionId | String | The transaction ID. | diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 41f8fe880..f2f8411b3 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -308,30 +308,41 @@ Each event type has a set of properties that are included as part of event's dat - [vm_unhealthy](vm-unhealthy.md) This event is triggered when a virtual machine is found to be unhealthy. -## Catalog +## CatalogV1 -- [item_created](item-created.md) +- [title_catalog_updated](catalogv1/title-catalog-updated.md) + This event is triggered when a catalog is changed. + +- [title_store_updated](catalogv1/title-store-updated.md) + This event is triggered when a store is changed. + +## CatalogV2 + +- [item_created](catalogv2/item-created.md) This event is triggered when an item is created. -- [item_deleted](item-deleted.md) +- [item_deleted](catalogv2/item-deleted.md) This event is triggered when an item is deleted. -- [item_moderation_state_changed](item-moderation-state-changed.md) +- [item_moderation_state_changed](catalogv2/item-moderation-state-changed.md) This event is triggered when an item moderation state is changed. -- [item_publish_requested](item-publish-requested.md) +- [item_publish_requested](catalogv2/item-publish-requested.md) This event is triggered when an publishing is started. -- [item_reported](item-reported.md) +- [item_purchased](catalogv2/item-purchased.md) + This event is triggered when an item is purchased. + +- [item_reported](catalogv2/item-reported.md) This event is triggered when an item is reported. -- [item_updated](item-updated.md) +- [item_updated](catalogv2/item-updated.md) This event is triggered when an item is updated. -- [review_reported](review-reported.md) +- [review_reported](catalogv2/review-reported.md) This event is triggered when a review is reported. -- [reviews_takedown_requested](reviews-takedown-requested.md) +- [reviews_takedown_requested](catalogv2/reviews-takedown-requested.md) Event trigged when a takedown of reviews is requested. ## Character @@ -349,29 +360,82 @@ Each event type has a set of properties that are included as part of event's dat - [character_virtual_currency_balance_changed](character-virtual-currency-balance-changed.md) This event is triggered when a character's virtual currency balance changes. -## Inventory +## InventoryV1 + +- [character_consumed_item](inventoryv1/character-consumed-item.md) + This event is triggered when a character consumes an item from their inventory. + +- [character_inventory_item_added](inventoryv1/character-inventory-item-added.md) + This event is triggered when an item is granted to a character. -- [items_added](items-added.md) +- [character_vc_item_purchased](inventoryv1/character-vc-item-purchased.md) + This event is triggered when the character makes a purchase using virtual currency. + +- [character_virtual_currency_balance_changed](inventoryv1/character-virtual-currency-balance-changed.md) + This event is triggered when a character's virtual currency balance changes. + +- [player_consumed_item](inventoryv1/player-consumed-item.md) + This event is triggered when a player consumes an item from their inventory. + +- [player_inventory_item_added](inventoryv1/player-inventory-item-added.md) + This event is triggered when an item is granted to a player. + +- [player_paid_for_purchase](inventoryv1/player-paid-for-purchase.md) + This event is triggered when the second step of the payment process completes, paying for the purchase. + +- [player_realmoney_purchase](inventoryv1/player-realmoney-purchase.md) + This event is triggered when a player makes a real money purchase, and generates revenue for the game. + +- [player_receipt_validation](inventoryv1/player-receipt-validation.md) + This event is triggered when a player attempts to make a real money purchase and the purchase receipt is being validated. + +- [player_redeemed_coupon](inventoryv1/player-redeemed-coupon.md) + This event is triggered when a player redeems a coupon. + +- [player_started_purchase](inventoryv1/player-started-purchase.md) + This event is triggered when a player starts a purchase. + +- [player_vc_item_purchased](inventoryv1/player-vc-item-purchased.md) + This event is triggered when the player makes a purchase using virtual currency. + +- [player_virtual_currency_balance_changed](inventoryv1/player-virtual-currency-balance-changed.md) + This event is triggered when a player's virtual currency balance changes. + +## InventoryV2 + +- [items_added](inventoryv2/items-added.md) Event raised when items have been added to an inventory. -- [items_deleted](items-deleted.md) +- [items_clawback_completed](inventoryv2/items-clawback-completed.md) + This event is triggered when an items clawback operation is completed. + +- [items_clawback_reversal_completed](inventoryv2/items-clawback-reversal-completed.md) + This event is triggered when an items clawback reversal operation is completed. + +- [items_deleted](inventoryv2/items-deleted.md) Event raised when items have been deleted from an inventory. -- [items_purchased](items-purchased.md) +- [items_expired](inventoryv2/items-expired.md) + This event is triggered when items have expired in an inventory. + +- [items_purchased](inventoryv2/items-purchased.md) Event raised when items have been purchased from an inventory. -- [items_redeemed](items-redeemed.md) +- [items_redeemed](inventoryv2/items-redeemed.md) Event raised when items have been redeemed to an inventory. -- [items_subtracted](items-subtracted.md) +- [items_subtracted](inventoryv2/items-subtracted.md) Event raised when items have been subtracted from an inventory. -- [items_transferred](items-transferred.md) +- [items_transferred](inventoryv2/items-transferred.md) Event raised when items have been transferred to or from an inventory. -- [items_updated](items-updated.md) +- [items_updated](inventoryv2/items-updated.md) Event raised when items have been updated in an inventory. +- [marketplace_transaction_redeemed](inventoryv2/marketplace-transaction-redeemed.md) + This event is triggered when a marketplace transaction is redeemed. + ## GameSave - [gamesave_version_finalized](GameSave/gamesave-version-finalized.md) diff --git a/playfab-docs/api-references/events/item-created.md b/playfab-docs/api-references/events/item-created.md deleted file mode 100644 index 36ef0832f..000000000 --- a/playfab-docs/api-references/events/item-created.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: item_created -author: fprotti96 -description: ItemCreated event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# item_created - -This event is triggered when an item is created. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|ItemId|String|The string of the item that was created.| -|ItemType|String|The string type of the item that was created.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/item-deleted.md b/playfab-docs/api-references/events/item-deleted.md deleted file mode 100644 index a70f683bd..000000000 --- a/playfab-docs/api-references/events/item-deleted.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: item_deleted -author: fprotti96 -description: ItemDeleted event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# item_deleted - -This event is triggered when an item is deleted. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|ItemId|String|The string ID of the item that was deleted.| -|ItemType|String|The string type of the item that was deleted.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/item-reported.md b/playfab-docs/api-references/events/item-reported.md deleted file mode 100644 index 74059702d..000000000 --- a/playfab-docs/api-references/events/item-reported.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: item_reported -author: fprotti96 -description: ItemReported event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# item_reported - -This event is triggered when an item is reported. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|ItemId|String|The string ID of the item that was reported.| -|ItemType|String|The string type of the item that was reported.| -|CreatorEntityKey|[EntityKey](data-types/entitykey.md)|The item's creator.| -|ConcernCategory|String|The category for which this item was reported.| -|Reason|String|The reason for which this item was reported.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-added.md b/playfab-docs/api-references/events/items-added.md deleted file mode 100644 index de1ca1b1c..000000000 --- a/playfab-docs/api-references/events/items-added.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: items_added -author: fprotti96 -description: ItemsAdded event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# items_added - -Event raised when items have been added to an inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|TransactionId|String|The transaction id.| -|CollectionId|String|The collection id.| -|ItemId|String|The item id.| -|StackId|String|The stack id.| -|Amount|int?|The amount of items that were added.| -|DurationInSeconds|long?|The duration of the item that was added.| -|ItemType|String|The type of the catalog item that was modified in the transaction.| -|Balance|int?|The balance of the items changed as a result of the transaction.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/items-deleted.md b/playfab-docs/api-references/events/items-deleted.md deleted file mode 100644 index 37e93c148..000000000 --- a/playfab-docs/api-references/events/items-deleted.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: items_deleted -author: fprotti96 -description: ItemsDeleted event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# items_deleted - -Event raised when items have been deleted from an inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|TransactionId|String|The transaction id.| -|CollectionId|String|The collection id.| -|ItemId|String|The item id.| -|StackId|String|The stack id.| -|ItemType|String|The type of the catalog item that was modified in the transaction.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/items-purchased.md b/playfab-docs/api-references/events/items-purchased.md deleted file mode 100644 index fa5a2e9e1..000000000 --- a/playfab-docs/api-references/events/items-purchased.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: items_purchased -author: fprotti96 -description: ItemsPurchased event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# items_purchased - -Event raised when items have been purchased from an inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|TransactionId|String|The transaction id.| -|CollectionId|String|The collection id.| -|ItemId|String|The item id.| -|StackId|String|The stack id.| -|Amount|int?|The amount of items that were puchased.| -|DurationInSeconds|long?|The duration of the item that was purchased.| -|SalePriceAmounts|List<[PurchasePriceAmount](data-types/purchasepriceamount.md)>|The per-item price amounts the item was purchased at.| -|StoreId|String|The id of the Store the item was purchased from or null.| -|ItemType|String|The type of the catalog item that was modified in the transaction.| -|Balance|int?|The balance of the items changed as a result of the transaction.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-redeemed.md b/playfab-docs/api-references/events/items-redeemed.md deleted file mode 100644 index 129d96071..000000000 --- a/playfab-docs/api-references/events/items-redeemed.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: items_redeemed -author: fprotti96 -description: ItemsRedeemed event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# items_redeemed - -Event raised when items have been redeemed to an inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|TransactionId|String|The transaction id.| -|CollectionId|String|The collection id.| -|ItemId|String|The item id.| -|StackId|String|The stack id.| -|Amount|int?|The amount of items that were redeemed.| -|DurationInSeconds|long?|The duration of the item that was redeemed.| -|Marketplace|String|The name of the marketplace that the items were redeemed from.| -|MarketplaceTransactionId|String|The transaction id in the marketplace that the items were redeemed from.| -|ItemType|String|The type of the catalog item that was modified in the transaction.| -|Balance|int?|The balance of the items changed as a result of the transaction.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-subtracted.md b/playfab-docs/api-references/events/items-subtracted.md deleted file mode 100644 index 4527c8821..000000000 --- a/playfab-docs/api-references/events/items-subtracted.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: items_subtracted -author: fprotti96 -description: ItemsSubtracted event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# items_subtracted - -Event raised when items have been subtracted from an inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|TransactionId|String|The transaction id.| -|CollectionId|String|The collection id.| -|ItemId|String|The item id.| -|StackId|String|The stack id.| -|Amount|int?|The amount of items that were subtracted.| -|DurationInSeconds|long?|The duration of the item that was subtracted.| -|ItemType|String|The type of the catalog item that was modified in the transaction.| -|Balance|int?|The balance of the items changed as a result of the transaction.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-transferred.md b/playfab-docs/api-references/events/items-transferred.md deleted file mode 100644 index 6ca8f8e5f..000000000 --- a/playfab-docs/api-references/events/items-transferred.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: items_transferred -author: fprotti96 -description: ItemsTransferred event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# items_transferred - -Event raised when items have been transferred to or from an inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|TransactionId|String|The transaction id.| -|CollectionId|String|The collection id.| -|ItemId|String|The item id.| -|StackId|String|The stack id.| -|Amount|int?|The amount of items that were transferred.| -|DurationInSeconds|long?|The duration of the item that was transferred.| -|GivingEntity|[EntityKey](data-types/entitykey.md)?|The entity the items were transferred from or null if it was the current entity.| -|ReceivingEntity|[EntityKey](data-types/entitykey.md)?|The entity the items were transferred to or null if it was the current entity.| -|GivingCollectionId|String|The collection if the items were transferred from or null if it was the current collection.| -|ReceivingCollectionId|String|The collection id the items were transferred to or null if it was the current collection.| -|ItemType|String|The type of the catalog item that was modified in the transaction.| -|Balance|int?|The balance of the items changed as a result of the transaction.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/items-updated.md b/playfab-docs/api-references/events/items-updated.md deleted file mode 100644 index 42d035b47..000000000 --- a/playfab-docs/api-references/events/items-updated.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: items_updated -author: fprotti96 -description: ItemsUpdated event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# items_updated - -Event raised when items have been updated in an inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|TransactionId|String|The transaction id.| -|CollectionId|String|The collection id.| -|ItemId|String|The item id.| -|StackId|String|The stack id.| -|Amount|int?|The amount of item.| -|Expiration|String|The date the item expires.| -|ItemType|String|The type of the catalog item that was modified in the transaction.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/marketplace-transaction-redeemed.md b/playfab-docs/api-references/events/marketplace-transaction-redeemed.md deleted file mode 100644 index ae32bd1de..000000000 --- a/playfab-docs/api-references/events/marketplace-transaction-redeemed.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: marketplace_transaction_redeemed -author: fprotti96 -description: marketplace_transaction_redeemed event. -ms.author: fprotti -ms.date: 04/26/2024 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# marketplace_transaction_redeemed - -This event is triggered when a bundle or subscription has been redeemed to an inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|Marketplace|String|The name of the marketplace the items were redeemed from.| -|MarketplaceTransctionId|String|The transaction Id from the marketplace the items were redeemed from.| -|MarketplaceAlternateId|String|The alternate Id of the item for the marketplace.| -|Amount|int?|The amount that was redeemed.| -|DurationInSeconds|long?|The amount of subscription that was redeemed.| -|ItemId|String|The identifier of the item that was redeemed.| -|ItemType|String|The type of the catalog item that was redeemed.| -|RealMoneyPrices|Dictionary|The multi-currency unit price, in real money, of the item that was redeemed. The property is a dictionary where the key is the three-letter currency code as defined in ISO 4217, and the value is the currency amount in the smallest unit (for example, cents, pence) in accordance with ISO 4217. Only United States Dollar (USD) is currently supported. Example: If the product price in USD is $1.39, the dictionary entry would be: ["USD"] = 139;| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/player-consumed-item.md b/playfab-docs/api-references/events/player-consumed-item.md deleted file mode 100644 index 9198c769e..000000000 --- a/playfab-docs/api-references/events/player-consumed-item.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: player_consumed_item -author: joannaleecy -description: player_consumed_item event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_consumed_item - -This event is triggered when a player consumes an item from their inventory. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CatalogVersion|String|Version of the catalog from which the consumed inventory item was created.| -|ItemId|String|ID of the catalog item from which the consumed inventory item was created. This can be used to look up the item from the catalog.| -|ItemInstanceId|String|The specific ID of the item that was consumed.| -|PreviousUsesRemaining|uint32|For multiple use items, the number of uses that remained before the item was consumed.| -|TitleId|String|The ID of the title to which this player event applies.| -|UsesRemaining|uint32|For multiple use items, the number of uses remaining after the item was consumed.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-inventory-item-added.md b/playfab-docs/api-references/events/player-inventory-item-added.md deleted file mode 100644 index d0a5e094a..000000000 --- a/playfab-docs/api-references/events/player-inventory-item-added.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: player_inventory_item_added -author: joannaleecy -description: player_inventory_item_added event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_inventory_item_added - -This event is triggered when an item is granted to a player. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|Annotation|String|Optional details about the inventory item.| -|BundleContents|[]|Catalog item IDs of any other items granted to the player along with this one as part of a bundle.| -|CatalogVersion|String|Catalog version in which the item that was added is defined.| -|Class|String|Class of the item that was added.| -|CouponCode|String|Redeemed coupon (if any) that granted the item.| -|DisplayName|String|Display name of the item that was added.| -|Expiration|DateTime|When the item expires. The value is null if the item does not expire.| -|InstanceId|String|Unique instance ID of the inventory item that was added.| -|ItemId|String|Catalog item ID of the inventory item that was added.| -|RemainingUses|uint32|How many uses the item has, if it has a limited number of uses.| -|TitleId|String|The ID of the title to which this player event applies.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-paid-for-purchase.md b/playfab-docs/api-references/events/player-paid-for-purchase.md deleted file mode 100644 index d61370899..000000000 --- a/playfab-docs/api-references/events/player-paid-for-purchase.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: player_paid_for_purchase -author: joannaleecy -description: player_paid_for_purchase event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_paid_for_purchase - -This event is triggered when the second step of the payment process completes, paying for the purchase. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|OrderId|String|Purchase order identifier.| -|ProviderData|String|Provider used for the transaction.| -|ProviderName|String|Payment provider to use to fund the purchase.| -|ProviderToken|String|A token generated by the provider to authenticate the request (provider-specific).| -|PurchaseConfirmationPageURL|String|URL to the purchase provider page that details the purchase.| -|PurchaseCurrency|String|Currency for the transaction, may be a virtual currency or real money.| -|PurchasePrice|uint32|Cost of the transaction.| -|Status|[TransactionStatus](data-types/transactionstatus.md)|Status of the transaction.| -|TitleId|String|The ID of the title to which this player event applies.| -|VirtualCurrencyBalances|Object|Current virtual currency balances for the user.| -|VirtualCurrencyGrants|Object|Virtual currencies granted by the transaction, if any.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-realmoney-purchase.md b/playfab-docs/api-references/events/player-realmoney-purchase.md deleted file mode 100644 index bcd43b8ff..000000000 --- a/playfab-docs/api-references/events/player-realmoney-purchase.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: player_realmoney_purchase -author: joannaleecy -description: player_realmoney_purchase event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_realmoney_purchase - -This event is triggered when a player makes a real money purchase, and generates revenue for the game. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|OrderId|String|Unique identifier of the order.| -|OrderTotal|uint32|Total value of the purchase in the system currency (defaults to USD).| -|PaymentProvider|String|Payment provider used to make the purchase.| -|PaymentType|[PaymentType](data-types/paymenttype.md)|Type of payment used to make the purchase.| -|PurchasedProduct|[]|The ItemIds from the catalog of the purchased items, if applicable.| -|TitleId|String|The ID of the title to which this player event applies.| -|TransactionCurrency|[Currency](data-types/currency.md)|Local currency used to make the purchase, if applicable.| -|TransactionId|String|Unique identifier of the transaction.| -|TransactionTotal|uint32|Total value of the purchase in the local currency used to make the purchase, if applicable.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-receipt-validation.md b/playfab-docs/api-references/events/player-receipt-validation.md deleted file mode 100644 index e6863fcd3..000000000 --- a/playfab-docs/api-references/events/player-receipt-validation.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: player_receipt_validation -author: joannaleecy -description: player_receipt_validation event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_receipt_validation - -This event is triggered when a player attempts to make a real money purchase and the purchase receipt is being validated. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|Error|String|The error that occurred during a receipt validation.| -|PaymentProvider|String|Payment provider used to make the purchase attempt.| -|PaymentType|[PaymentType](data-types/paymenttype.md)|Type of payment used to make the purchase attempt.| -|ReceiptContent|String|The receipt data during a real money purchase event attempt.| -|TitleId|String|The ID of the title to which this player event applies.| -|Valid|Boolean|Indicates if the receipt is valid.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-redeemed-coupon.md b/playfab-docs/api-references/events/player-redeemed-coupon.md deleted file mode 100644 index bbd75a90c..000000000 --- a/playfab-docs/api-references/events/player-redeemed-coupon.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: player_redeemed_coupon -author: joannaleecy -description: player_redeemed_coupon event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_redeemed_coupon - -This event is triggered when a player redeems a coupon. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CouponCode|String|Coupon code the player redeemed.| -|GrantedInventoryItems|[CouponGrantedInventoryItem](data-types/coupongrantedinventoryitem.md)|Items added to the player's inventory by redeeming the coupon.| -|TitleId|String|The ID of the title to which this player event applies.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-started-purchase.md b/playfab-docs/api-references/events/player-started-purchase.md deleted file mode 100644 index 2f34a3ef9..000000000 --- a/playfab-docs/api-references/events/player-started-purchase.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: player_started_purchase -author: joannaleecy -description: player_started_purchase event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_started_purchase - -This event is triggered when a player starts a purchase. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CatalogVersion|String|Catalog version for the items to be purchased. Defaults to most recent catalog.| -|Contents|[CartItem](data-types/cartitem.md)|Cart items to be purchased.| -|OrderId|String|Purchase order identifier.| -|StoreId|String|Store through which to purchase items. If not set, prices will be pulled from the catalog itself.| -|TitleId|String|The ID of the title to which this player event applies.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-vc-item-purchased.md b/playfab-docs/api-references/events/player-vc-item-purchased.md deleted file mode 100644 index a6633a480..000000000 --- a/playfab-docs/api-references/events/player-vc-item-purchased.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: player_vc_item_purchased -author: joannaleecy -description: player_vc_item_purchased event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_vc_item_purchased - -This event is triggered when the player makes a purchase using virtual currency. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CatalogVersion|String|Version of the catalog from which the item was purchased.| -|CurrencyCode|String|Currency that was used to purchase the item.| -|ItemId|String|Identifier of the catalog item that was purchased.| -|PurchaseId|String|Unique identifier of the purchase transaction.| -|Quantity|int32|Quantity of items that were purchased.| -|StoreId|String|The StoreId where the item was purchased.| -|TitleId|String|The ID of the title to which this player event applies.| -|UnitPrice|uint32|Price paid per item, expressed in the virtual currency.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-virtual-currency-balance-changed.md b/playfab-docs/api-references/events/player-virtual-currency-balance-changed.md deleted file mode 100644 index 98f0fc5b8..000000000 --- a/playfab-docs/api-references/events/player-virtual-currency-balance-changed.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: player_virtual_currency_balance_changed -author: joannaleecy -description: player_virtual_currency_balance_changed event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# player_virtual_currency_balance_changed - -This event is triggered when a player's virtual currency balance changes. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|OrderId|String|Id of the order that triggered the balance changes| -|TitleId|String|The ID of the title to which this player event applies.| -|VirtualCurrencyBalance|int32|New virtual currency balance after the change.| -|VirtualCurrencyName|String|Virtual currency whose balance changed.| -|VirtualCurrencyPreviousBalance|int32|Old virtual currency balance before the change.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/review-reported.md b/playfab-docs/api-references/events/review-reported.md deleted file mode 100644 index 40fd565dd..000000000 --- a/playfab-docs/api-references/events/review-reported.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: review_reported -author: fprotti96 -description: ReviewReported event. -ms.author: fprotti -ms.date: 09/29/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# review_reported - -This event is triggered when a review is reported. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|ItemId|String|The string ID of the item associated with the review.| -|ReviewId|String|The string ID of the review being reported.| -|ConcernCategory|String|The category for which this review was reported.| -|Reason|String|The string reason for this report.| -|CreatorEntityKey|[EntityKey](data-types/entitykey.md)|The EntityKey of the creator of the review that was reported.| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/title-store-updated.md b/playfab-docs/api-references/events/title-store-updated.md deleted file mode 100644 index 1a5261799..000000000 --- a/playfab-docs/api-references/events/title-store-updated.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: title_store_updated -author: joannaleecy -description: title_store_updated event. -ms.author: jenelleb -ms.date: 02/19/2019 -ms.topic: article -ms.service: azure-playfab -keywords: playfab, playstream events -ms.localizationpriority: medium ---- - -# title_store_updated - -This event is triggered when a store is changed. - -## Properties - -|Name|Type|Description| -| :--------------------|:-------------------|:----------------------| -|CatalogVersion|String|Catalog version that the updated store belongs to.| -|Deleted|Boolean|Was the store deleted.| -|DeveloperId|String|| -|StoreId|String|ID of the updated store.| -|UserId|String|| - -## Common Properties - -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] From 5349e5689386894ea5080c44bd921132234c87b4 Mon Sep 17 00:00:00 2001 From: Andy McCalib Date: Thu, 19 Feb 2026 09:43:08 -0800 Subject: [PATCH 50/76] docs: Document when it's safe to write during Game Saves upload (#2820) Add guidance to the Game Saves quickstart explaining that once the sync state transitions to Uploading, local save files have been captured and the game can safely write to the save folder again. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jason Sandlin --- playfab-docs/player-progression/game-saves/quickstart.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/playfab-docs/player-progression/game-saves/quickstart.md b/playfab-docs/player-progression/game-saves/quickstart.md index a2c3dfcca..187b07c92 100644 --- a/playfab-docs/player-progression/game-saves/quickstart.md +++ b/playfab-docs/player-progression/game-saves/quickstart.md @@ -278,6 +278,12 @@ if (FAILED(hr)) // Success! Save data is now safely stored in the cloud ``` +### When can I write to the save folder again? + +During upload, the system reads and compresses your local save files before uploading them. Once the sync state transitions to `Uploading` (reported via `PFGameSaveFilesUiProgressCallback`), the system has finished reading your files and it's safe to write to the save folder again. You don't need to wait for the full upload to complete before resuming saves. + +If you aren't using the progress callback, wait for the `XAsyncBlock` to complete before writing new save data. + ### Best Practices 1. **Handle failures gracefully**: Network issues shouldn't crash your game 2. **Use appropriate options**: From a0b321255a9964a549047c2063aed1ceb3d2f8d8 Mon Sep 17 00:00:00 2001 From: anaisnlawson Date: Thu, 19 Feb 2026 19:08:13 -0500 Subject: [PATCH 51/76] Stub in page for opt-in events (#2824) * Stub in page for opt-in events * Added steps for Event Configuration usage * fixed formatting and language * Add Foundation Mode exception * draft of content for opt-in events * Edits to doc name * Clarify that this experience is for service-generated events only, not custom events * modified some language * modify language of bulk edits --------- Co-authored-by: kdearnley Co-authored-by: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> --- .../ingest-data/opt-in-events.md | 105 ++++++++++++++++++ .../data-analytics/ingest-data/toc.yml | 2 + 2 files changed, 107 insertions(+) create mode 100644 playfab-docs/data-analytics/ingest-data/opt-in-events.md diff --git a/playfab-docs/data-analytics/ingest-data/opt-in-events.md b/playfab-docs/data-analytics/ingest-data/opt-in-events.md new file mode 100644 index 000000000..b7d56f995 --- /dev/null +++ b/playfab-docs/data-analytics/ingest-data/opt-in-events.md @@ -0,0 +1,105 @@ +--- +title: Enable or Disable Service Generated Events +description: "Learn how to configure PlayStream, Telemetry, and disabled event types in PlayFab Game Manager to optimize data collection and automation." +author: anaisnlawson +ms.author: anaislawson +ms.service: playfab +ms.topic: tutorial, playstream, telemetry, events +ms.date: 02/19/2026 +--- + +# Enable or Disable Service Generated Events + +PlayFab events capture player and game data for analytics and automation. Understanding how to configure event types in Game Manager helps you optimize data collection costs while meeting your game's needs. All events that are [generated by PlayFab services](../../api-references/events/index.md) can be enabled or disabled as using the Event Configuration settings. + +## Navigate to Event Configuration + +Event Configuration is located in the Settings area of Game Manager: + +1. Sign in to [Game Manager](https://developer.playfab.com). +1. Select your title from the title list. +1. In the left navigation, select **Settings** > **Event Configuration**. + +The Event Configuration page displays all available events organized by PlayFab product (Data, Economy, Multiplayer, etc.). + +## Understand event types + +Each event can be configured as one of three types: + +**PlayStream events:** + +- Process in real-time for immediate automation +- Trigger rules, CloudScript, and segment updates +- Higher metering cost per event +- Best for LiveOps, rewards, and real-time reactions + +**Telemetry events:** + +- Send directly to data lake for analytics only +- Lower metering cost per event +- No real-time automation capabilities +- Best for metrics, logging, and deferred analysis + +**None:** + +- Event is not collected or processed +- No cost or functionality +- Use to completely disable unused events + +## Filter and search events + +The Event Configuration interface provides several ways to find specific events: + +- **Search:** Enter part of an event name or namespace in the search box. Results filter automatically across all product tabs. +- **Filter by type:** Select the **Filter events** dropdown and choose **PlayStream**, **Telemetry**, **None**, or **All**. +- **Clear filters:** Select the **Clear** button next to the filters to remove all search and type restrictions. + +## Change event types + +Events are organized by PlayFab product (Data, Economy, Multiplayer, etc.). Each product tab shows the count of events it contains. + +To change an event type: + +1. Select the product tab containing your event. +1. Locate the event you want to configure. +1. Select the **Event Type** dropdown and choose **PlayStream**, **Telemetry**, or **None**. +1. The change is marked as unsaved until you save. + +> [!NOTE] +> Some events have mandatory types that cannot be changed. These events show their required type without a dropdown. + +To preview event data, select the graph icon next to any event. A data explorer popup shows recent event instances from the last 7 days. + +> [!IMPORTANT] +> The data explorer has a 7-day lookback period and cannot retrieve older event data. + +## Use bulk operations + +To disable multiple events at once: + +1. Select **Bulk Edit Events** in the header. +1. Choose **Set all PlayStream events to none** or **Set all telemetry events to none** (or both). +1. Select **Apply** to make the changes. +1. Review the toast notification and the unsaved changes indicator, then **Save** or **Discard Changes** as needed. + +## Save configuration changes + +After changing event types: + +1. Select **Save** in the page header or at the bottom of the page. +1. Review the confirmation dialog, which shows all pending changes organized by product. +1. Select **Save** to apply or **Discard Changes** to revert all unsaved modifications. + +> [!NOTE] +> Game Manager shows a confirmation dialog if you navigate away with unsaved changes. + +## Next steps + +After changing event types, verify that any automation rules still reference active PlayStream events and that your analytics reports reflect the updated configuration. + +Learn more about working with events in PlayFab: + +- [PlayStream Event Model reference](../../api-references/events/index.md) +- [PlayStream events documentation](playstream-events) +- [PlayStream actions and rules for automation](../acting-data/action-rules-overview.md) +- [Telemetry events overview](telemetry-overview.md) diff --git a/playfab-docs/data-analytics/ingest-data/toc.yml b/playfab-docs/data-analytics/ingest-data/toc.yml index 0d9586bd7..a6e069b0c 100644 --- a/playfab-docs/data-analytics/ingest-data/toc.yml +++ b/playfab-docs/data-analytics/ingest-data/toc.yml @@ -41,3 +41,5 @@ items: href: ht-telemetry-keys-delete.md - name: Activate or Deactivate Telemetry Keys href: ht-activate-deactivate-telemetry-keys.md + - name: Enable or Disable Service Generated Events + href: opt-in-events.md From 45b44ecfbef0e180cdf857d7918039cb5a7149fd Mon Sep 17 00:00:00 2001 From: "Valexa O." <46427879+valexao@users.noreply.github.com> Date: Thu, 19 Feb 2026 19:22:17 -0800 Subject: [PATCH 52/76] Fix to Restructure Playstream Events Page Links + Add folders to align with categories + Remove dupes (#2819) * fix toc.yml * move MPS events to MPS folder * update * rm group_deleted references since it was already deleted * Add folders for AdPlacement, CatologV1, Character, General, InventoryV1, Partner, Player, Title, Session, and general events * rm inventoryv1 dupes * fix build report suggestions * fix broken links from outside of api-references/events folder * acrolinx fixes for legacy release notes --- .../{ => AdPlacement}/player-ad-closed.md | 2 +- .../{ => AdPlacement}/player-ad-ended.md | 2 +- .../{ => AdPlacement}/player-ad-opened.md | 2 +- .../{ => AdPlacement}/player-ad-rewarded.md | 2 +- .../{ => AdPlacement}/player-ad-started.md | 2 +- .../character-consumed-item.md | 0 .../character-inventory-item-added.md | 0 .../character-vc-item-purchased.md | 0 ...racter-virtual-currency-balance-changed.md | 0 ...ntity-virtual-currency-balances-changed.md | 4 +- .../{ => General}/studio-tier-updated.md | 6 +- .../tenancy-connector-onboard.md | 4 +- .../{InventoryV2 => Inventory}/items-added.md | 0 .../items-clawback-completed.md | 0 .../items-clawback-reversal-completed.md | 0 .../items-deleted.md | 0 .../items-expired.md | 0 .../items-purchased.md | 0 .../items-redeemed.md | 0 .../items-subtracted.md | 0 .../items-transferred.md | 0 .../items-updated.md | 0 .../marketplace-transaction-redeemed.md | 0 .../build-alias-created.md | 6 +- .../build-alias-deleted.md | 6 +- .../build-alias-updated.md | 6 +- .../{ => MultiplayerServers}/build-deleted.md | 6 +- .../build-region-status-changed.md | 6 +- .../build-region-updated.md | 6 +- .../build-region-utilization.md | 6 +- .../certificate-deleted.md | 6 +- .../certificate-uploaded.md | 6 +- .../crash-detected.md | 6 +- .../create-build-initiated.md | 6 +- .../enabled-for-title.md | 4 +- .../game-asset-deleted.md | 6 +- .../monitoring-output-saved.md | 6 +- .../{ => MultiplayerServers}/secret-added.md | 6 +- .../secret-deleted.md | 6 +- .../server-requested.md | 6 +- .../server-state-changed.md | 6 +- .../{ => MultiplayerServers}/vm-assigned.md | 6 +- .../vm-game-certificates-deployed.md | 6 +- .../vm-remote-user-created.md | 6 +- .../vm-remote-user-deleted.md | 6 +- .../vm-state-change.md | 6 +- .../vm-unassignment-started.md | 6 +- .../{ => MultiplayerServers}/vm-unhealthy.md | 6 +- .../{ => Partner}/display-name-filtered.md | 2 +- .../player-display-name-filtered.md | 2 +- .../player-photon-session-authenticated.md | 4 +- .../{ => Player}/player-action-executed.md | 8 +- .../player-ad-campaign-attribution.md | 2 +- .../player-consumed-item.md | 0 .../player-inventory-item-added.md | 0 .../player-paid-for-purchase.md | 0 .../player-realmoney-purchase.md | 0 .../player-receipt-validation.md | 0 .../player-redeemed-coupon.md | 0 .../player-set-profile-property.md | 4 +- .../player-started-purchase.md | 0 .../player-vc-item-purchased.md | 0 ...player-virtual-currency-balance-changed.md | 0 .../{ => Session}/client-focus-change.md | 8 +- .../{ => Session}/client-session-start.md | 8 +- .../title-client-rate-limited-alert.md | 6 +- .../title-high-error-rate-alert.md | 6 +- .../title-requested-limit-change.md | 4 +- .../events/{ => Title}/title-saved-survey.md | 2 +- playfab-docs/api-references/events/index.md | 195 ++--- playfab-docs/api-references/toc.yml | 675 +++++++++++------- ...derboards-with-playstream-and-telemetry.md | 8 +- ...ing-cloudscript-actions-with-playstream.md | 8 +- .../ingest-data/playstream-events.md | 2 +- .../data-analytics/ingest-data/sessions.md | 4 +- .../learn-data/trends/trends-overview.md | 18 +- .../gdpr-exporting-player-data.md | 2 +- .../economy/items/quickstart.md | 2 +- .../economy/stores/quickstart.md | 2 +- playfab-docs/multiplayer/matchmaking/index.md | 4 +- ...tatistics-with-playstream-and-telemetry.md | 2 +- playfab-docs/release-notes/2016.md | 344 ++++----- playfab-docs/release-notes/2017.md | 298 ++++---- playfab-docs/release-notes/2018.md | 150 ++-- 84 files changed, 1010 insertions(+), 932 deletions(-) rename playfab-docs/api-references/events/{ => AdPlacement}/player-ad-closed.md (89%) rename playfab-docs/api-references/events/{ => AdPlacement}/player-ad-ended.md (89%) rename playfab-docs/api-references/events/{ => AdPlacement}/player-ad-opened.md (89%) rename playfab-docs/api-references/events/{ => AdPlacement}/player-ad-rewarded.md (91%) rename playfab-docs/api-references/events/{ => AdPlacement}/player-ad-started.md (89%) rename playfab-docs/api-references/events/{InventoryV1 => Character}/character-consumed-item.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Character}/character-inventory-item-added.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Character}/character-vc-item-purchased.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Character}/character-virtual-currency-balance-changed.md (100%) rename playfab-docs/api-references/events/{ => General}/entity-virtual-currency-balances-changed.md (84%) rename playfab-docs/api-references/events/{ => General}/studio-tier-updated.md (74%) rename playfab-docs/api-references/events/{ => General}/tenancy-connector-onboard.md (74%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-added.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-clawback-completed.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-clawback-reversal-completed.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-deleted.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-expired.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-purchased.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-redeemed.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-subtracted.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-transferred.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/items-updated.md (100%) rename playfab-docs/api-references/events/{InventoryV2 => Inventory}/marketplace-transaction-redeemed.md (100%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/build-alias-created.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/build-alias-deleted.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/build-alias-updated.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/build-deleted.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/build-region-status-changed.md (59%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/build-region-updated.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/build-region-utilization.md (59%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/certificate-deleted.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/certificate-uploaded.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/crash-detected.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/create-build-initiated.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/enabled-for-title.md (71%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/game-asset-deleted.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/monitoring-output-saved.md (60%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/secret-added.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/secret-deleted.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/server-requested.md (59%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/server-state-changed.md (59%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/vm-assigned.md (59%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/vm-game-certificates-deployed.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/vm-remote-user-created.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/vm-remote-user-deleted.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/vm-state-change.md (59%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/vm-unassignment-started.md (58%) rename playfab-docs/api-references/events/{ => MultiplayerServers}/vm-unhealthy.md (58%) rename playfab-docs/api-references/events/{ => Partner}/display-name-filtered.md (89%) rename playfab-docs/api-references/events/{ => Partner}/player-display-name-filtered.md (89%) rename playfab-docs/api-references/events/{ => Partner}/player-photon-session-authenticated.md (77%) rename playfab-docs/api-references/events/{ => Player}/player-action-executed.md (64%) rename playfab-docs/api-references/events/{ => Player}/player-ad-campaign-attribution.md (89%) rename playfab-docs/api-references/events/{InventoryV1 => Player}/player-consumed-item.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Player}/player-inventory-item-added.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Player}/player-paid-for-purchase.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Player}/player-realmoney-purchase.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Player}/player-receipt-validation.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Player}/player-redeemed-coupon.md (100%) rename playfab-docs/api-references/events/{ => Player}/player-set-profile-property.md (76%) rename playfab-docs/api-references/events/{InventoryV1 => Player}/player-started-purchase.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Player}/player-vc-item-purchased.md (100%) rename playfab-docs/api-references/events/{InventoryV1 => Player}/player-virtual-currency-balance-changed.md (100%) rename playfab-docs/api-references/events/{ => Session}/client-focus-change.md (68%) rename playfab-docs/api-references/events/{ => Session}/client-session-start.md (67%) rename playfab-docs/api-references/events/{ => Title}/title-client-rate-limited-alert.md (72%) rename playfab-docs/api-references/events/{ => Title}/title-high-error-rate-alert.md (71%) rename playfab-docs/api-references/events/{ => Title}/title-requested-limit-change.md (88%) rename playfab-docs/api-references/events/{ => Title}/title-saved-survey.md (90%) diff --git a/playfab-docs/api-references/events/player-ad-closed.md b/playfab-docs/api-references/events/AdPlacement/player-ad-closed.md similarity index 89% rename from playfab-docs/api-references/events/player-ad-closed.md rename to playfab-docs/api-references/events/AdPlacement/player-ad-closed.md index 11e092b58..72c7bfca8 100644 --- a/playfab-docs/api-references/events/player-ad-closed.md +++ b/playfab-docs/api-references/events/AdPlacement/player-ad-closed.md @@ -27,4 +27,4 @@ This event is triggered when a player closes an ad. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-ended.md b/playfab-docs/api-references/events/AdPlacement/player-ad-ended.md similarity index 89% rename from playfab-docs/api-references/events/player-ad-ended.md rename to playfab-docs/api-references/events/AdPlacement/player-ad-ended.md index 2a5954134..4ae866eee 100644 --- a/playfab-docs/api-references/events/player-ad-ended.md +++ b/playfab-docs/api-references/events/AdPlacement/player-ad-ended.md @@ -27,4 +27,4 @@ This event is triggered when a player finishes an ad. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-opened.md b/playfab-docs/api-references/events/AdPlacement/player-ad-opened.md similarity index 89% rename from playfab-docs/api-references/events/player-ad-opened.md rename to playfab-docs/api-references/events/AdPlacement/player-ad-opened.md index 4ee11dfb8..5759ce16d 100644 --- a/playfab-docs/api-references/events/player-ad-opened.md +++ b/playfab-docs/api-references/events/AdPlacement/player-ad-opened.md @@ -27,4 +27,4 @@ This event is triggered when a player opens an ad. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-rewarded.md b/playfab-docs/api-references/events/AdPlacement/player-ad-rewarded.md similarity index 91% rename from playfab-docs/api-references/events/player-ad-rewarded.md rename to playfab-docs/api-references/events/AdPlacement/player-ad-rewarded.md index 9e707ebbd..2f9cc9a77 100644 --- a/playfab-docs/api-references/events/player-ad-rewarded.md +++ b/playfab-docs/api-references/events/AdPlacement/player-ad-rewarded.md @@ -29,4 +29,4 @@ This event is triggered when a player recieves an ad reward. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-started.md b/playfab-docs/api-references/events/AdPlacement/player-ad-started.md similarity index 89% rename from playfab-docs/api-references/events/player-ad-started.md rename to playfab-docs/api-references/events/AdPlacement/player-ad-started.md index 28b48f5a5..c85ae5e2f 100644 --- a/playfab-docs/api-references/events/player-ad-started.md +++ b/playfab-docs/api-references/events/AdPlacement/player-ad-started.md @@ -27,4 +27,4 @@ This event is triggered when a player starts an ad. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/character-consumed-item.md b/playfab-docs/api-references/events/Character/character-consumed-item.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/character-consumed-item.md rename to playfab-docs/api-references/events/Character/character-consumed-item.md diff --git a/playfab-docs/api-references/events/InventoryV1/character-inventory-item-added.md b/playfab-docs/api-references/events/Character/character-inventory-item-added.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/character-inventory-item-added.md rename to playfab-docs/api-references/events/Character/character-inventory-item-added.md diff --git a/playfab-docs/api-references/events/InventoryV1/character-vc-item-purchased.md b/playfab-docs/api-references/events/Character/character-vc-item-purchased.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/character-vc-item-purchased.md rename to playfab-docs/api-references/events/Character/character-vc-item-purchased.md diff --git a/playfab-docs/api-references/events/InventoryV1/character-virtual-currency-balance-changed.md b/playfab-docs/api-references/events/Character/character-virtual-currency-balance-changed.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/character-virtual-currency-balance-changed.md rename to playfab-docs/api-references/events/Character/character-virtual-currency-balance-changed.md diff --git a/playfab-docs/api-references/events/entity-virtual-currency-balances-changed.md b/playfab-docs/api-references/events/General/entity-virtual-currency-balances-changed.md similarity index 84% rename from playfab-docs/api-references/events/entity-virtual-currency-balances-changed.md rename to playfab-docs/api-references/events/General/entity-virtual-currency-balances-changed.md index 039f7a733..8aa3135fc 100644 --- a/playfab-docs/api-references/events/entity-virtual-currency-balances-changed.md +++ b/playfab-docs/api-references/events/General/entity-virtual-currency-balances-changed.md @@ -19,7 +19,7 @@ This event is triggered when an entity's virtual currency balance changes. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |SequenceId|String|Sequence id of the balance change to ensure updates are processed in order.| |VirtualCurrencyBalances|Object|New virtual currency balances after the change. Only shows currencies that were updated.| |VirtualCurrencyContainerId|String|Container whose balances changed.| @@ -27,4 +27,4 @@ This event is triggered when an entity's virtual currency balance changes. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/studio-tier-updated.md b/playfab-docs/api-references/events/General/studio-tier-updated.md similarity index 74% rename from playfab-docs/api-references/events/studio-tier-updated.md rename to playfab-docs/api-references/events/General/studio-tier-updated.md index 5de1d38f9..ae6017eda 100644 --- a/playfab-docs/api-references/events/studio-tier-updated.md +++ b/playfab-docs/api-references/events/General/studio-tier-updated.md @@ -23,9 +23,9 @@ This event is triggered when a studio tier is updated. |IsReservedCapacity|Boolean|IsReservedCapacity PaymentOption| |IsReservedCapacityAnnual|Boolean|IsReservedCapacityAnnual PaymentOption| |MonthlyMinimumUSD|double|Monthly Minimum Price in USD| -|OveragePricePerMauTiers|[PaymentOptionPerMauPriceTier](data-types/paymentoptionpermaupricetier.md)|OveragePricePerMauTiers Definitions| +|OveragePricePerMauTiers|[PaymentOptionPerMauPriceTier](../data-types/paymentoptionpermaupricetier.md)|OveragePricePerMauTiers Definitions| |PaymentSystemAccountId|String|Payment System AccountId| -|PricePerMauTiers|[PaymentOptionPerMauPriceTier](data-types/paymentoptionpermaupricetier.md)|PricePerMauTiers Definitions| +|PricePerMauTiers|[PaymentOptionPerMauPriceTier](../data-types/paymentoptionpermaupricetier.md)|PricePerMauTiers Definitions| |ReservedMAU|int32|Reserved Capacity MAU| |StudioIds|IEnumerable_String|Studio Ids| |TierDisplayName|String|Tier Display Name| @@ -34,4 +34,4 @@ This event is triggered when a studio tier is updated. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/tenancy-connector-onboard.md b/playfab-docs/api-references/events/General/tenancy-connector-onboard.md similarity index 74% rename from playfab-docs/api-references/events/tenancy-connector-onboard.md rename to playfab-docs/api-references/events/General/tenancy-connector-onboard.md index 4eb3a8897..dc088a253 100644 --- a/playfab-docs/api-references/events/tenancy-connector-onboard.md +++ b/playfab-docs/api-references/events/General/tenancy-connector-onboard.md @@ -19,8 +19,8 @@ This event is triggered when a tenancy connector is onboarded. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |EntityChain|String|The chain of ownership for this entity.| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV2/items-added.md b/playfab-docs/api-references/events/Inventory/items-added.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-added.md rename to playfab-docs/api-references/events/Inventory/items-added.md diff --git a/playfab-docs/api-references/events/InventoryV2/items-clawback-completed.md b/playfab-docs/api-references/events/Inventory/items-clawback-completed.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-clawback-completed.md rename to playfab-docs/api-references/events/Inventory/items-clawback-completed.md diff --git a/playfab-docs/api-references/events/InventoryV2/items-clawback-reversal-completed.md b/playfab-docs/api-references/events/Inventory/items-clawback-reversal-completed.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-clawback-reversal-completed.md rename to playfab-docs/api-references/events/Inventory/items-clawback-reversal-completed.md diff --git a/playfab-docs/api-references/events/InventoryV2/items-deleted.md b/playfab-docs/api-references/events/Inventory/items-deleted.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-deleted.md rename to playfab-docs/api-references/events/Inventory/items-deleted.md diff --git a/playfab-docs/api-references/events/InventoryV2/items-expired.md b/playfab-docs/api-references/events/Inventory/items-expired.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-expired.md rename to playfab-docs/api-references/events/Inventory/items-expired.md diff --git a/playfab-docs/api-references/events/InventoryV2/items-purchased.md b/playfab-docs/api-references/events/Inventory/items-purchased.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-purchased.md rename to playfab-docs/api-references/events/Inventory/items-purchased.md diff --git a/playfab-docs/api-references/events/InventoryV2/items-redeemed.md b/playfab-docs/api-references/events/Inventory/items-redeemed.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-redeemed.md rename to playfab-docs/api-references/events/Inventory/items-redeemed.md diff --git a/playfab-docs/api-references/events/InventoryV2/items-subtracted.md b/playfab-docs/api-references/events/Inventory/items-subtracted.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-subtracted.md rename to playfab-docs/api-references/events/Inventory/items-subtracted.md diff --git a/playfab-docs/api-references/events/InventoryV2/items-transferred.md b/playfab-docs/api-references/events/Inventory/items-transferred.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-transferred.md rename to playfab-docs/api-references/events/Inventory/items-transferred.md diff --git a/playfab-docs/api-references/events/InventoryV2/items-updated.md b/playfab-docs/api-references/events/Inventory/items-updated.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/items-updated.md rename to playfab-docs/api-references/events/Inventory/items-updated.md diff --git a/playfab-docs/api-references/events/InventoryV2/marketplace-transaction-redeemed.md b/playfab-docs/api-references/events/Inventory/marketplace-transaction-redeemed.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV2/marketplace-transaction-redeemed.md rename to playfab-docs/api-references/events/Inventory/marketplace-transaction-redeemed.md diff --git a/playfab-docs/api-references/events/build-alias-created.md b/playfab-docs/api-references/events/MultiplayerServers/build-alias-created.md similarity index 58% rename from playfab-docs/api-references/events/build-alias-created.md rename to playfab-docs/api-references/events/MultiplayerServers/build-alias-created.md index aa9694760..dc6876e83 100644 --- a/playfab-docs/api-references/events/build-alias-created.md +++ b/playfab-docs/api-references/events/MultiplayerServers/build-alias-created.md @@ -18,9 +18,9 @@ This event is triggered when a multiplayer server build alias is created. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[BuildAliasCreatedEventPayload](data-types/buildaliascreatedeventpayload.md)|The multiplayer server build alias created event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[BuildAliasCreatedEventPayload](../data-types/buildaliascreatedeventpayload.md)|The multiplayer server build alias created event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-alias-deleted.md b/playfab-docs/api-references/events/MultiplayerServers/build-alias-deleted.md similarity index 58% rename from playfab-docs/api-references/events/build-alias-deleted.md rename to playfab-docs/api-references/events/MultiplayerServers/build-alias-deleted.md index babf5b7f0..2efb262db 100644 --- a/playfab-docs/api-references/events/build-alias-deleted.md +++ b/playfab-docs/api-references/events/MultiplayerServers/build-alias-deleted.md @@ -18,9 +18,9 @@ This event is triggered when a multiplayer server build alias is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[BuildAliasDeletedEventPayload](data-types/buildaliasdeletedeventpayload.md)|The multiplayer server build alias deleted event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[BuildAliasDeletedEventPayload](../data-types/buildaliasdeletedeventpayload.md)|The multiplayer server build alias deleted event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-alias-updated.md b/playfab-docs/api-references/events/MultiplayerServers/build-alias-updated.md similarity index 58% rename from playfab-docs/api-references/events/build-alias-updated.md rename to playfab-docs/api-references/events/MultiplayerServers/build-alias-updated.md index 69d72c93b..f38ba6ddc 100644 --- a/playfab-docs/api-references/events/build-alias-updated.md +++ b/playfab-docs/api-references/events/MultiplayerServers/build-alias-updated.md @@ -18,10 +18,10 @@ This event is triggered when a multiplayer server build alias is updated. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[BuildAliasUpdatedEventPayload](data-types/buildaliasupdatedeventpayload.md)|The multiplayer server build alias updated event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[BuildAliasUpdatedEventPayload](../data-types/buildaliasupdatedeventpayload.md)|The multiplayer server build alias updated event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-deleted.md b/playfab-docs/api-references/events/MultiplayerServers/build-deleted.md similarity index 58% rename from playfab-docs/api-references/events/build-deleted.md rename to playfab-docs/api-references/events/MultiplayerServers/build-deleted.md index fdbe4f5a7..879a71f2a 100644 --- a/playfab-docs/api-references/events/build-deleted.md +++ b/playfab-docs/api-references/events/MultiplayerServers/build-deleted.md @@ -18,11 +18,11 @@ This event is triggered when a multiplayer server build is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[BuildDeletedEventPayload](data-types/builddeletedeventpayload.md)|The multiplayer server build deleted event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[BuildDeletedEventPayload](../data-types/builddeletedeventpayload.md)|The multiplayer server build deleted event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-region-status-changed.md b/playfab-docs/api-references/events/MultiplayerServers/build-region-status-changed.md similarity index 59% rename from playfab-docs/api-references/events/build-region-status-changed.md rename to playfab-docs/api-references/events/MultiplayerServers/build-region-status-changed.md index 0471bdc63..9fbde8d41 100644 --- a/playfab-docs/api-references/events/build-region-status-changed.md +++ b/playfab-docs/api-references/events/MultiplayerServers/build-region-status-changed.md @@ -18,11 +18,11 @@ This event is triggered when a multiplayer server's build region status is chang |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[BuildRegionStatusChangedEventPayload](data-types/buildregionstatuschangedeventpayload.md)|The multiplayer server build region status changed event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[BuildRegionStatusChangedEventPayload](../data-types/buildregionstatuschangedeventpayload.md)|The multiplayer server build region status changed event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-region-updated.md b/playfab-docs/api-references/events/MultiplayerServers/build-region-updated.md similarity index 58% rename from playfab-docs/api-references/events/build-region-updated.md rename to playfab-docs/api-references/events/MultiplayerServers/build-region-updated.md index 44ca49a79..d218f959a 100644 --- a/playfab-docs/api-references/events/build-region-updated.md +++ b/playfab-docs/api-references/events/MultiplayerServers/build-region-updated.md @@ -18,10 +18,10 @@ This event is triggered when a multiplayer server build region is updated. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[BuildRegionUpdatedEventPayload](data-types/buildregionupdatedeventpayload.md)|The multiplayer server build region updated event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[BuildRegionUpdatedEventPayload](../data-types/buildregionupdatedeventpayload.md)|The multiplayer server build region updated event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/build-region-utilization.md b/playfab-docs/api-references/events/MultiplayerServers/build-region-utilization.md similarity index 59% rename from playfab-docs/api-references/events/build-region-utilization.md rename to playfab-docs/api-references/events/MultiplayerServers/build-region-utilization.md index 0a87a9e95..5b75dddae 100644 --- a/playfab-docs/api-references/events/build-region-utilization.md +++ b/playfab-docs/api-references/events/MultiplayerServers/build-region-utilization.md @@ -18,10 +18,10 @@ This event is triggered to display the utilization of servers for a build in eac |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[BuildRegionUtilizationEventPayload](data-types/buildregionutilizationeventpayload.md)|The multiplayer server build region utilization event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[BuildRegionUtilizationEventPayload](../data-types/buildregionutilizationeventpayload.md)|The multiplayer server build region utilization event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/certificate-deleted.md b/playfab-docs/api-references/events/MultiplayerServers/certificate-deleted.md similarity index 58% rename from playfab-docs/api-references/events/certificate-deleted.md rename to playfab-docs/api-references/events/MultiplayerServers/certificate-deleted.md index 5f4987aa9..bd0b45ac5 100644 --- a/playfab-docs/api-references/events/certificate-deleted.md +++ b/playfab-docs/api-references/events/MultiplayerServers/certificate-deleted.md @@ -18,9 +18,9 @@ This event is triggered when a multiplayer server certificate is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[CertificateDeletedEventPayload](data-types/certificatedeletedeventpayload.md)|The multiplayer server certificate deleted event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[CertificateDeletedEventPayload](../data-types/certificatedeletedeventpayload.md)|The multiplayer server certificate deleted event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/certificate-uploaded.md b/playfab-docs/api-references/events/MultiplayerServers/certificate-uploaded.md similarity index 58% rename from playfab-docs/api-references/events/certificate-uploaded.md rename to playfab-docs/api-references/events/MultiplayerServers/certificate-uploaded.md index 6a334d05b..242515001 100644 --- a/playfab-docs/api-references/events/certificate-uploaded.md +++ b/playfab-docs/api-references/events/MultiplayerServers/certificate-uploaded.md @@ -18,10 +18,10 @@ This event is triggered when a multiplayer server certificate is uploaded. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[CertificateUploadedEventPayload](data-types/certificateuploadedeventpayload.md)|The multiplayer server certificate uploaded event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[CertificateUploadedEventPayload](../data-types/certificateuploadedeventpayload.md)|The multiplayer server certificate uploaded event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/crash-detected.md b/playfab-docs/api-references/events/MultiplayerServers/crash-detected.md similarity index 58% rename from playfab-docs/api-references/events/crash-detected.md rename to playfab-docs/api-references/events/MultiplayerServers/crash-detected.md index 9f3e6a6c7..97aa6da30 100644 --- a/playfab-docs/api-references/events/crash-detected.md +++ b/playfab-docs/api-references/events/MultiplayerServers/crash-detected.md @@ -18,10 +18,10 @@ This event triggered when a crash dump is found on a terminating server. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[CrashDetectedEventPayload](data-types/crashdetectedeventpayload.md)|The multiplayer server crash detected event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[CrashDetectedEventPayload](../data-types/crashdetectedeventpayload.md)|The multiplayer server crash detected event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/create-build-initiated.md b/playfab-docs/api-references/events/MultiplayerServers/create-build-initiated.md similarity index 58% rename from playfab-docs/api-references/events/create-build-initiated.md rename to playfab-docs/api-references/events/MultiplayerServers/create-build-initiated.md index 0eeba5338..6b4178de0 100644 --- a/playfab-docs/api-references/events/create-build-initiated.md +++ b/playfab-docs/api-references/events/MultiplayerServers/create-build-initiated.md @@ -18,10 +18,10 @@ This event is triggered when a multiplayer server build is initiated. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[CreateBuildInitiatedEventPayload](data-types/createbuildinitiatedeventpayload.md)|The multiplayer server create build initiated event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[CreateBuildInitiatedEventPayload](../data-types/createbuildinitiatedeventpayload.md)|The multiplayer server create build initiated event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/enabled-for-title.md b/playfab-docs/api-references/events/MultiplayerServers/enabled-for-title.md similarity index 71% rename from playfab-docs/api-references/events/enabled-for-title.md rename to playfab-docs/api-references/events/MultiplayerServers/enabled-for-title.md index 5cd64b4aa..aede9c264 100644 --- a/playfab-docs/api-references/events/enabled-for-title.md +++ b/playfab-docs/api-references/events/MultiplayerServers/enabled-for-title.md @@ -18,9 +18,9 @@ This event is triggered when a title enables PlayFab multiplayer servers. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/game-asset-deleted.md b/playfab-docs/api-references/events/MultiplayerServers/game-asset-deleted.md similarity index 58% rename from playfab-docs/api-references/events/game-asset-deleted.md rename to playfab-docs/api-references/events/MultiplayerServers/game-asset-deleted.md index 09bd007f6..233d75081 100644 --- a/playfab-docs/api-references/events/game-asset-deleted.md +++ b/playfab-docs/api-references/events/MultiplayerServers/game-asset-deleted.md @@ -17,10 +17,10 @@ This event is triggered when a multiplayer server game asset is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[GameAssetDeletedEventPayload](data-types/gameassetdeletedeventpayload.md)|The multiplayer server game asset deleted event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[GameAssetDeletedEventPayload](../data-types/gameassetdeletedeventpayload.md)|The multiplayer server game asset deleted event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/monitoring-output-saved.md b/playfab-docs/api-references/events/MultiplayerServers/monitoring-output-saved.md similarity index 60% rename from playfab-docs/api-references/events/monitoring-output-saved.md rename to playfab-docs/api-references/events/MultiplayerServers/monitoring-output-saved.md index 75c5680d2..cb925f258 100644 --- a/playfab-docs/api-references/events/monitoring-output-saved.md +++ b/playfab-docs/api-references/events/MultiplayerServers/monitoring-output-saved.md @@ -18,10 +18,10 @@ This event is triggered when the output of a monitoring application has been sav |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[MonitoringOutputSavedEventPayload](data-types/monitoringoutputsavedeventpayload.md)|The multiplayer server monitoring output saved event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[MonitoringOutputSavedEventPayload](../data-types/monitoringoutputsavedeventpayload.md)|The multiplayer server monitoring output saved event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/secret-added.md b/playfab-docs/api-references/events/MultiplayerServers/secret-added.md similarity index 58% rename from playfab-docs/api-references/events/secret-added.md rename to playfab-docs/api-references/events/MultiplayerServers/secret-added.md index f8d08f1ff..a2b6e452f 100644 --- a/playfab-docs/api-references/events/secret-added.md +++ b/playfab-docs/api-references/events/MultiplayerServers/secret-added.md @@ -18,10 +18,10 @@ This event is triggered when a multiplayer server secret is added. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[SecretAddedEventPayload](data-types/secretaddedeventpayload.md)|The multiplayer server secret added event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[SecretAddedEventPayload](../data-types/secretaddedeventpayload.md)|The multiplayer server secret added event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/secret-deleted.md b/playfab-docs/api-references/events/MultiplayerServers/secret-deleted.md similarity index 58% rename from playfab-docs/api-references/events/secret-deleted.md rename to playfab-docs/api-references/events/MultiplayerServers/secret-deleted.md index a32aee78f..9d77ea608 100644 --- a/playfab-docs/api-references/events/secret-deleted.md +++ b/playfab-docs/api-references/events/MultiplayerServers/secret-deleted.md @@ -18,10 +18,10 @@ This event is triggered when a multiplayer server secret is deleted. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[SecretDeletedEventPayload](data-types/secretdeletedeventpayload.md)|The multiplayer server secret deleted event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[SecretDeletedEventPayload](../data-types/secretdeletedeventpayload.md)|The multiplayer server secret deleted event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/server-requested.md b/playfab-docs/api-references/events/MultiplayerServers/server-requested.md similarity index 59% rename from playfab-docs/api-references/events/server-requested.md rename to playfab-docs/api-references/events/MultiplayerServers/server-requested.md index 08f9b556a..027a8b192 100644 --- a/playfab-docs/api-references/events/server-requested.md +++ b/playfab-docs/api-references/events/MultiplayerServers/server-requested.md @@ -18,13 +18,13 @@ This event is triggered when a multiplayer server is requested. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[ServerRequestedEventPayload](data-types/serverrequestedeventpayload.md)|The multiplayer server requested event payload.| +|Payload|[ServerRequestedEventPayload](../data-types/serverrequestedeventpayload.md)|The multiplayer server requested event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/server-state-changed.md b/playfab-docs/api-references/events/MultiplayerServers/server-state-changed.md similarity index 59% rename from playfab-docs/api-references/events/server-state-changed.md rename to playfab-docs/api-references/events/MultiplayerServers/server-state-changed.md index a07a1b372..3497ef503 100644 --- a/playfab-docs/api-references/events/server-state-changed.md +++ b/playfab-docs/api-references/events/MultiplayerServers/server-state-changed.md @@ -18,11 +18,11 @@ This event is triggered when a multiplayer server's state is changed. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[ServerStateChangedEventPayload](data-types/serverstatechangedeventpayload.md)|The multiplayer server state changed event payload.| +|Payload|[ServerStateChangedEventPayload](../data-types/serverstatechangedeventpayload.md)|The multiplayer server state changed event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-assigned.md b/playfab-docs/api-references/events/MultiplayerServers/vm-assigned.md similarity index 59% rename from playfab-docs/api-references/events/vm-assigned.md rename to playfab-docs/api-references/events/MultiplayerServers/vm-assigned.md index 050f9d82b..c93fe6935 100644 --- a/playfab-docs/api-references/events/vm-assigned.md +++ b/playfab-docs/api-references/events/MultiplayerServers/vm-assigned.md @@ -18,9 +18,9 @@ This event is triggered when a virtual machine is assigned to a multiplayer serv |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[VmAssignedEventPayload](data-types/vmassignedeventpayload.md)|The multiplayer server virtual machine assigned event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[VmAssignedEventPayload](../data-types/vmassignedeventpayload.md)|The multiplayer server virtual machine assigned event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-game-certificates-deployed.md b/playfab-docs/api-references/events/MultiplayerServers/vm-game-certificates-deployed.md similarity index 58% rename from playfab-docs/api-references/events/vm-game-certificates-deployed.md rename to playfab-docs/api-references/events/MultiplayerServers/vm-game-certificates-deployed.md index d5c8f4206..464d13966 100644 --- a/playfab-docs/api-references/events/vm-game-certificates-deployed.md +++ b/playfab-docs/api-references/events/MultiplayerServers/vm-game-certificates-deployed.md @@ -18,9 +18,9 @@ This event is triggered when game certificates are deployed in a game virtual ma |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[VmGameCertificatesDeployedEventPayload](data-types/vmgamecertificatesdeployedeventpayload.md)|The multiplayer server vm game certificates deployed event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[VmGameCertificatesDeployedEventPayload](../data-types/vmgamecertificatesdeployedeventpayload.md)|The multiplayer server vm game certificates deployed event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/vm-remote-user-created.md b/playfab-docs/api-references/events/MultiplayerServers/vm-remote-user-created.md similarity index 58% rename from playfab-docs/api-references/events/vm-remote-user-created.md rename to playfab-docs/api-references/events/MultiplayerServers/vm-remote-user-created.md index c2a19609a..88b86a32f 100644 --- a/playfab-docs/api-references/events/vm-remote-user-created.md +++ b/playfab-docs/api-references/events/MultiplayerServers/vm-remote-user-created.md @@ -18,9 +18,9 @@ This event is triggered when a multiplayer server virtual machine remote user is |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[VmRemoteUserCreatedEventPayload](data-types/vmremoteusercreatedeventpayload.md)|The multiplayer server virtual machine remote user created event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[VmRemoteUserCreatedEventPayload](../data-types/vmremoteusercreatedeventpayload.md)|The multiplayer server virtual machine remote user created event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-remote-user-deleted.md b/playfab-docs/api-references/events/MultiplayerServers/vm-remote-user-deleted.md similarity index 58% rename from playfab-docs/api-references/events/vm-remote-user-deleted.md rename to playfab-docs/api-references/events/MultiplayerServers/vm-remote-user-deleted.md index d3fb0b72c..2e82fb175 100644 --- a/playfab-docs/api-references/events/vm-remote-user-deleted.md +++ b/playfab-docs/api-references/events/MultiplayerServers/vm-remote-user-deleted.md @@ -18,9 +18,9 @@ This event is triggered when a multiplayer server virtual machine remote user is |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[VmRemoteUserDeletedEventPayload](data-types/vmremoteuserdeletedeventpayload.md)|The multiplayer server virtual machine remote user deleted event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[VmRemoteUserDeletedEventPayload](../data-types/vmremoteuserdeletedeventpayload.md)|The multiplayer server virtual machine remote user deleted event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-state-change.md b/playfab-docs/api-references/events/MultiplayerServers/vm-state-change.md similarity index 59% rename from playfab-docs/api-references/events/vm-state-change.md rename to playfab-docs/api-references/events/MultiplayerServers/vm-state-change.md index f26bd9350..6a6222891 100644 --- a/playfab-docs/api-references/events/vm-state-change.md +++ b/playfab-docs/api-references/events/MultiplayerServers/vm-state-change.md @@ -18,10 +18,10 @@ This event is triggered when a multiplayer virtual machine's state is changed. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[VmStateChangeEventPayload](data-types/vmstatechangeeventpayload.md)|The multiplayer server vm state change event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[VmStateChangeEventPayload](../data-types/vmstatechangeeventpayload.md)|The multiplayer server vm state change event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-unassignment-started.md b/playfab-docs/api-references/events/MultiplayerServers/vm-unassignment-started.md similarity index 58% rename from playfab-docs/api-references/events/vm-unassignment-started.md rename to playfab-docs/api-references/events/MultiplayerServers/vm-unassignment-started.md index 17ef1a416..8de176d81 100644 --- a/playfab-docs/api-references/events/vm-unassignment-started.md +++ b/playfab-docs/api-references/events/MultiplayerServers/vm-unassignment-started.md @@ -17,9 +17,9 @@ This event is triggered when a virtual machine is unassigned from a multiplayer |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[VmUnassignmentStartedEventPayload](data-types/vmunassignmentstartedeventpayload.md)|The multiplayer server virtual machine unassignment started event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[VmUnassignmentStartedEventPayload](../data-types/vmunassignmentstartedeventpayload.md)|The multiplayer server virtual machine unassignment started event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/vm-unhealthy.md b/playfab-docs/api-references/events/MultiplayerServers/vm-unhealthy.md similarity index 58% rename from playfab-docs/api-references/events/vm-unhealthy.md rename to playfab-docs/api-references/events/MultiplayerServers/vm-unhealthy.md index c72655d16..2034fcf5a 100644 --- a/playfab-docs/api-references/events/vm-unhealthy.md +++ b/playfab-docs/api-references/events/MultiplayerServers/vm-unhealthy.md @@ -17,9 +17,9 @@ This event is triggered when a virtual machine is found to be unhealthy. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| -|Payload|[VmUnhealthyEventPayload](data-types/vmunhealthyeventpayload.md)|The multiplayer server virtual machine unhealthy event payload.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| +|Payload|[VmUnhealthyEventPayload](../data-types/vmunhealthyeventpayload.md)|The multiplayer server virtual machine unhealthy event payload.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] \ No newline at end of file +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/display-name-filtered.md b/playfab-docs/api-references/events/Partner/display-name-filtered.md similarity index 89% rename from playfab-docs/api-references/events/display-name-filtered.md rename to playfab-docs/api-references/events/Partner/display-name-filtered.md index 4bfc95247..40bfb0168 100644 --- a/playfab-docs/api-references/events/display-name-filtered.md +++ b/playfab-docs/api-references/events/Partner/display-name-filtered.md @@ -23,4 +23,4 @@ This event is triggered when a display name is filtered by community sift. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-display-name-filtered.md b/playfab-docs/api-references/events/Partner/player-display-name-filtered.md similarity index 89% rename from playfab-docs/api-references/events/player-display-name-filtered.md rename to playfab-docs/api-references/events/Partner/player-display-name-filtered.md index f8227fdaf..7230f362c 100644 --- a/playfab-docs/api-references/events/player-display-name-filtered.md +++ b/playfab-docs/api-references/events/Partner/player-display-name-filtered.md @@ -23,4 +23,4 @@ This event is triggered when a display name is filtered by community sift only i ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-photon-session-authenticated.md b/playfab-docs/api-references/events/Partner/player-photon-session-authenticated.md similarity index 77% rename from playfab-docs/api-references/events/player-photon-session-authenticated.md rename to playfab-docs/api-references/events/Partner/player-photon-session-authenticated.md index 874d5c28a..33d37d248 100644 --- a/playfab-docs/api-references/events/player-photon-session-authenticated.md +++ b/playfab-docs/api-references/events/Partner/player-photon-session-authenticated.md @@ -19,9 +19,9 @@ Properties |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |PhotonApplicationId|String|Unique identifier of the Photon Cloud application to which the player is connected| -|PhotonApplicationType|[PhotonServicesEnum](data-types/photonservicesenum.md)|Type of Photon Cloud application to which the player is connected| +|PhotonApplicationType|[PhotonServicesEnum](../data-types/photonservicesenum.md)|Type of Photon Cloud application to which the player is connected| |TitleId|String|The ID of the title to which this player event applies.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-action-executed.md b/playfab-docs/api-references/events/Player/player-action-executed.md similarity index 64% rename from playfab-docs/api-references/events/player-action-executed.md rename to playfab-docs/api-references/events/Player/player-action-executed.md index 3f3b624b9..34ce3707a 100644 --- a/playfab-docs/api-references/events/player-action-executed.md +++ b/playfab-docs/api-references/events/Player/player-action-executed.md @@ -19,15 +19,15 @@ Properties |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |ActionName|String|Name of the action that was triggered.| -|Error|[ActionExecutionError](data-types/actionexecutionerror.md)|Information about the error that occurred during execution, if it failed to complete.| +|Error|[ActionExecutionError](../data-types/actionexecutionerror.md)|Information about the error that occurred during execution, if it failed to complete.| |ExecutionDuration|double|Action execution time in milliseconds.| |ExecutionResult|object|The object returned from the action execution, if it completed.| |ScheduledTimestamp|DateTime|Time that the action was scheduled for execution.| |TitleId|String|The ID of the title to which this player event applies.| |TriggeredTimestamp|DateTime|Time that the triggering event or segmentation change occurred.| -|TriggeringEventRuleMatch|[EventRuleMatch](data-types/eventrulematch.md)|Event rule match, if any, that triggered the action.| -|TriggeringSegmentMembershipChange|[SegmentMembershipChange](data-types/segmentmembershipchange.md)|Player segmentation change, if any, that triggered the action.| +|TriggeringEventRuleMatch|[EventRuleMatch](../data-types/eventrulematch.md)|Event rule match, if any, that triggered the action.| +|TriggeringSegmentMembershipChange|[SegmentMembershipChange](../data-types/segmentmembershipchange.md)|Player segmentation change, if any, that triggered the action.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/player-ad-campaign-attribution.md b/playfab-docs/api-references/events/Player/player-ad-campaign-attribution.md similarity index 89% rename from playfab-docs/api-references/events/player-ad-campaign-attribution.md rename to playfab-docs/api-references/events/Player/player-ad-campaign-attribution.md index f65135bbc..63492ad71 100644 --- a/playfab-docs/api-references/events/player-ad-campaign-attribution.md +++ b/playfab-docs/api-references/events/Player/player-ad-campaign-attribution.md @@ -23,4 +23,4 @@ This event is triggered by an attribution tracking Add-on when a player is match ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-consumed-item.md b/playfab-docs/api-references/events/Player/player-consumed-item.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/player-consumed-item.md rename to playfab-docs/api-references/events/Player/player-consumed-item.md diff --git a/playfab-docs/api-references/events/InventoryV1/player-inventory-item-added.md b/playfab-docs/api-references/events/Player/player-inventory-item-added.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/player-inventory-item-added.md rename to playfab-docs/api-references/events/Player/player-inventory-item-added.md diff --git a/playfab-docs/api-references/events/InventoryV1/player-paid-for-purchase.md b/playfab-docs/api-references/events/Player/player-paid-for-purchase.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/player-paid-for-purchase.md rename to playfab-docs/api-references/events/Player/player-paid-for-purchase.md diff --git a/playfab-docs/api-references/events/InventoryV1/player-realmoney-purchase.md b/playfab-docs/api-references/events/Player/player-realmoney-purchase.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/player-realmoney-purchase.md rename to playfab-docs/api-references/events/Player/player-realmoney-purchase.md diff --git a/playfab-docs/api-references/events/InventoryV1/player-receipt-validation.md b/playfab-docs/api-references/events/Player/player-receipt-validation.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/player-receipt-validation.md rename to playfab-docs/api-references/events/Player/player-receipt-validation.md diff --git a/playfab-docs/api-references/events/InventoryV1/player-redeemed-coupon.md b/playfab-docs/api-references/events/Player/player-redeemed-coupon.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/player-redeemed-coupon.md rename to playfab-docs/api-references/events/Player/player-redeemed-coupon.md diff --git a/playfab-docs/api-references/events/player-set-profile-property.md b/playfab-docs/api-references/events/Player/player-set-profile-property.md similarity index 76% rename from playfab-docs/api-references/events/player-set-profile-property.md rename to playfab-docs/api-references/events/Player/player-set-profile-property.md index 6654394ec..ff32528c2 100644 --- a/playfab-docs/api-references/events/player-set-profile-property.md +++ b/playfab-docs/api-references/events/Player/player-set-profile-property.md @@ -18,10 +18,10 @@ This event is triggered when PlayFab makes an internal adjustment to a player pr |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|Property|[PlayerProfileProperty](data-types/playerprofileproperty.md)|Property of the profile to be set| +|Property|[PlayerProfileProperty](../data-types/playerprofileproperty.md)|Property of the profile to be set| |TitleId|String|The ID of the title to which this player event applies.| |Value|object|Value to set to| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/InventoryV1/player-started-purchase.md b/playfab-docs/api-references/events/Player/player-started-purchase.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/player-started-purchase.md rename to playfab-docs/api-references/events/Player/player-started-purchase.md diff --git a/playfab-docs/api-references/events/InventoryV1/player-vc-item-purchased.md b/playfab-docs/api-references/events/Player/player-vc-item-purchased.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/player-vc-item-purchased.md rename to playfab-docs/api-references/events/Player/player-vc-item-purchased.md diff --git a/playfab-docs/api-references/events/InventoryV1/player-virtual-currency-balance-changed.md b/playfab-docs/api-references/events/Player/player-virtual-currency-balance-changed.md similarity index 100% rename from playfab-docs/api-references/events/InventoryV1/player-virtual-currency-balance-changed.md rename to playfab-docs/api-references/events/Player/player-virtual-currency-balance-changed.md diff --git a/playfab-docs/api-references/events/client-focus-change.md b/playfab-docs/api-references/events/Session/client-focus-change.md similarity index 68% rename from playfab-docs/api-references/events/client-focus-change.md rename to playfab-docs/api-references/events/Session/client-focus-change.md index f6b179762..a237869b7 100644 --- a/playfab-docs/api-references/events/client-focus-change.md +++ b/playfab-docs/api-references/events/Session/client-focus-change.md @@ -18,12 +18,12 @@ This event is triggered every time the application enters or exits focus on the |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[ClientFocusChangePayload](data-types/clientfocuschangepayload.md)|Payload that this entity is a child of.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| +|Payload|[ClientFocusChangePayload](../data-types/clientfocuschangepayload.md)|Payload that this entity is a child of.| +|WriterEntity|[EntityKey](../data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/client-session-start.md b/playfab-docs/api-references/events/Session/client-session-start.md similarity index 67% rename from playfab-docs/api-references/events/client-session-start.md rename to playfab-docs/api-references/events/Session/client-session-start.md index 04046abf0..99048619c 100644 --- a/playfab-docs/api-references/events/client-session-start.md +++ b/playfab-docs/api-references/events/Session/client-session-start.md @@ -18,12 +18,12 @@ Properties |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|EntityLineage|[EntityLineage](data-types/entitylineage.md)|Entities that this entity is a child of.| +|EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |OriginalEventId|String|The original unique identifier associated with this event before it was posted to PlayFab. The value might differ from the EventId value, which is assigned when the event is received by the server.| |OriginalTimestamp|DateTime|The original time (in UTC) associated with this event before it was posted to PlayFab. The value might differ from the Timestamp value, which is set at the time the event is received by the server.| -|Payload|[ClientSessionStartPayload](data-types/clientsessionstartpayload.md)|Payload that this entity is a child of.| -|WriterEntity|[EntityKey](data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| +|Payload|[ClientSessionStartPayload](../data-types/clientsessionstartpayload.md)|Payload that this entity is a child of.| +|WriterEntity|[EntityKey](../data-types/entitykey.md)|Entity that wrote this event, included only if different than the event's entity.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv2.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/title-client-rate-limited-alert.md b/playfab-docs/api-references/events/Title/title-client-rate-limited-alert.md similarity index 72% rename from playfab-docs/api-references/events/title-client-rate-limited-alert.md rename to playfab-docs/api-references/events/Title/title-client-rate-limited-alert.md index 7ce5e82b7..fc6af2867 100644 --- a/playfab-docs/api-references/events/title-client-rate-limited-alert.md +++ b/playfab-docs/api-references/events/Title/title-client-rate-limited-alert.md @@ -19,12 +19,12 @@ This event is triggered when a single IP address generates too many API calls to |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |AlertEventId|String|Unique identifier of the alert that triggered this event.| -|AlertState|[AlertStates](data-types/alertstates.md)|State of the alert. Values include Triggered, Recovered, ReTriggered.| +|AlertState|[AlertStates](../data-types/alertstates.md)|State of the alert. Values include Triggered, Recovered, ReTriggered.| |API|String|The PlayFab API that was called too frequently.| |ErrorCode|String|Error message that was returned to the client.| |GraphUrl|String|URL of an image graph of the counter that triggered the alert.| -|Level|[AlertLevel](data-types/alertlevel.md)|Level of the alert. Values include Warn, Alert, Critical.| +|Level|[AlertLevel](../data-types/alertlevel.md)|Level of the alert. Values include Warn, Alert, Critical.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-high-error-rate-alert.md b/playfab-docs/api-references/events/Title/title-high-error-rate-alert.md similarity index 71% rename from playfab-docs/api-references/events/title-high-error-rate-alert.md rename to playfab-docs/api-references/events/Title/title-high-error-rate-alert.md index 258a46e21..cb6bbf794 100644 --- a/playfab-docs/api-references/events/title-high-error-rate-alert.md +++ b/playfab-docs/api-references/events/Title/title-high-error-rate-alert.md @@ -19,12 +19,12 @@ This event is triggered when a game title experiences a high rate of errors. |Name|Type|Description| | :--------------------|:-------------------|:----------------------| |AlertEventId|String|Unique identifier of the alert that triggered this event.| -|AlertState|[AlertStates](data-types/alertstates.md)|State of the alert. Values include Triggered, Recovered, ReTriggered.| +|AlertState|[AlertStates](../data-types/alertstates.md)|State of the alert. Values include Triggered, Recovered, ReTriggered.| |API|String|The PlayFab API that is generating the high rate of errors.| |ErrorCode|String|Error message that was returned to the client.| |GraphUrl|String|URL of an image graph of the counter that triggered the alert.| -|Level|[AlertLevel](data-types/alertlevel.md)|Level of the alert. Values include Warn, Alert, Critical.| +|Level|[AlertLevel](../data-types/alertlevel.md)|Level of the alert. Values include Warn, Alert, Critical.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-requested-limit-change.md b/playfab-docs/api-references/events/Title/title-requested-limit-change.md similarity index 88% rename from playfab-docs/api-references/events/title-requested-limit-change.md rename to playfab-docs/api-references/events/Title/title-requested-limit-change.md index c4b52b7fd..a8b358f27 100644 --- a/playfab-docs/api-references/events/title-requested-limit-change.md +++ b/playfab-docs/api-references/events/Title/title-requested-limit-change.md @@ -27,10 +27,10 @@ This event is triggered when a title requests a service limit change. |PreviousValue|double|The limit value at the time of the requested change, if any.| |PriceUSD|double|The price of the requested limit level in US Dollars, if any.| |TransactionId|String|The unique identifier of the requested limit change transaction.| -|Unit|[MetricUnit](data-types/metricunit.md)|The unit of the limit requested to change.| +|Unit|[MetricUnit](../data-types/metricunit.md)|The unit of the limit requested to change.| |UserId|String|| |Value|double|The limit value of the requested change, if any.| ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/title-saved-survey.md b/playfab-docs/api-references/events/Title/title-saved-survey.md similarity index 90% rename from playfab-docs/api-references/events/title-saved-survey.md rename to playfab-docs/api-references/events/Title/title-saved-survey.md index 0291fac07..28834ba88 100644 --- a/playfab-docs/api-references/events/title-saved-survey.md +++ b/playfab-docs/api-references/events/Title/title-saved-survey.md @@ -27,4 +27,4 @@ This event is triggered when a game's survey is saved. ## Common Properties -[!INCLUDE [common-properties](../../includes/_common-properties-eventsv1.md)] +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index f2f8411b3..51dea43a3 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -18,19 +18,19 @@ Each event type has a set of properties that are included as part of event's dat ## AdPlacement -- [player_ad_closed](player-ad-closed.md) +- [player_ad_closed](AdPlacement/player-ad-closed.md) This event is triggered when a player closes an ad. -- [player_ad_ended](player-ad-ended.md) +- [player_ad_ended](AdPlacement/player-ad-ended.md) This event is triggered when a player finishes an ad. -- [player_ad_opened](player-ad-opened.md) +- [player_ad_opened](AdPlacement/player-ad-opened.md) This event is triggered when a player opens an ad. -- [player_ad_rewarded](player-ad-rewarded.md) +- [player_ad_rewarded](AdPlacement/player-ad-rewarded.md) This event is triggered when a player recieves an ad reward. -- [player_ad_started](player-ad-started.md) +- [player_ad_started](AdPlacement/player-ad-started.md) This event is triggered when a player starts an ad. ## Addons @@ -206,16 +206,13 @@ Each event type has a set of properties that are included as part of event's dat ## General -- [entity_virtual_currency_balances_changed](entity-virtual-currency-balances-changed.md) +- [entity_virtual_currency_balances_changed](General/entity-virtual-currency-balances-changed.md) This event is triggered when an entity's virtual currency balance changes. -- [group_deleted](group-deleted.md) - This event is triggered when an entity group is deleted. - -- [tenancy_connector_onboard](tenancy-connector-onboard.md) +- [tenancy_connector_onboard](General/tenancy-connector-onboard.md) This event is triggered when a tenancy connector is onboarded. -- [studio_tier_updated](studio-tier-updated.md) +- [studio_tier_updated](General/studio-tier-updated.md) This event is triggered when a studio tier is updated. ## Matchmaking @@ -233,87 +230,87 @@ Each event type has a set of properties that are included as part of event's dat ## Multiplayer Servers -- [build_alias_created](build-alias-created.md) +- [build_alias_created](MultiplayerServers/build-alias-created.md) This event is triggered when a multiplayer server build alias is created. -- [build_alias_deleted](build-alias-deleted.md) +- [build_alias_deleted](MultiplayerServers/build-alias-deleted.md) This event is triggered when a multiplayer server build alias is deleted. -- [build_alias_updated](build-alias-updated.md) +- [build_alias_updated](MultiplayerServers/build-alias-updated.md) This event is triggered when a multiplayer server build alias is updated. -- [build_deleted](build-deleted.md) +- [build_deleted](MultiplayerServers/build-deleted.md) This event is triggered when a multiplayer server build is deleted. -- [build_region_status_changed](build-region-status-changed.md) +- [build_region_status_changed](MultiplayerServers/build-region-status-changed.md) This event is triggered when a multiplayer server's build region status is changed. -- [build_region_updated](build-region-updated.md) +- [build_region_updated](MultiplayerServers/build-region-updated.md) This event is triggered when a multiplayer server build region is updated. -- [build_region_utilization](build-region-utilization.md) +- [build_region_utilization](MultiplayerServers/build-region-utilization.md) This event is triggered to display the utilization of servers for a build in each region. -- [certificate_deleted](certificate-deleted.md) +- [certificate_deleted](MultiplayerServers/certificate-deleted.md) This event is triggered when a multiplayer server certificate is deleted. -- [certificate_uploaded](certificate-uploaded.md) +- [certificate_uploaded](MultiplayerServers/certificate-uploaded.md) This event is triggered when a multiplayer server certificate is uploaded. -- [crash_detected](crash-detected.md) +- [crash_detected](MultiplayerServers/crash-detected.md) This event triggered when a crash dump is found on a terminating server. -- [create_build_initiated](create-build-initiated.md) +- [create_build_initiated](MultiplayerServers/create-build-initiated.md) This event is triggered when a multiplayer server build is initiated. -- [enabled_for_title](enabled-for-title.md) +- [enabled_for_title](MultiplayerServers/enabled-for-title.md) This event is triggered when a title enables PlayFab servers -- [game_asset_deleted](game-asset-deleted.md) +- [game_asset_deleted](MultiplayerServers/game-asset-deleted.md) This event is triggered when a multiplayer server game asset is deleted. -- [monitoring_output_saved](monitoring-output-saved.md) +- [monitoring_output_saved](MultiplayerServers/monitoring-output-saved.md) This event is triggered when the output of a monitoring application has been saved and can be downloaded. -- [secret_added](secret-added.md) +- [secret_added](MultiplayerServers/secret-added.md) This event is triggered when a multiplayer server secret is added. -- [secret_deleted](secret-deleted.md) +- [secret_deleted](MultiplayerServers/secret-deleted.md) This event is triggered when a multiplayer server secret is deleted. -- [server_requested](server-requested.md) +- [server_requested](MultiplayerServers/server-requested.md) This event is triggered when a multiplayer server is requested. -- [server_state_changed](server-state-changed.md) +- [server_state_changed](MultiplayerServers/server-state-changed.md) This event is triggered when a multiplayer server's state is changed. -- [vm_assigned](vm-assigned.md) +- [vm_assigned](MultiplayerServers/vm-assigned.md) This event is triggered when a virtual machine is assigned to a multiplayer server build. -- [vm_game_certificates_deployed](vm-game-certificates-deployed.md) +- [vm_game_certificates_deployed](MultiplayerServers/vm-game-certificates-deployed.md) This event is triggered when game certificates are deployed in a game virtual machine. -- [vm_remote_user_created](vm-remote-user-created.md) +- [vm_remote_user_created](MultiplayerServers/vm-remote-user-created.md) This event is triggered when a multiplayer server virtual machine remote user is created. -- [vm_remote_user_deleted](vm-remote-user-deleted.md) +- [vm_remote_user_deleted](MultiplayerServers/vm-remote-user-deleted.md) This event is triggered when a multiplayer server virtual machine remote user is deleted. -- [vm_state_change](vm-state-change.md) +- [vm_state_change](MultiplayerServers/vm-state-change.md) This event is triggered when a multiplayer virtual machine's state is changed. -- [vm_unassignment_started](vm-unassignment-started.md) +- [vm_unassignment_started](MultiplayerServers/vm-unassignment-started.md) This event is triggered when a virtual machine is unassigned from a multiplayer server build. -- [vm_unhealthy](vm-unhealthy.md) +- [vm_unhealthy](MultiplayerServers/vm-unhealthy.md) This event is triggered when a virtual machine is found to be unhealthy. ## CatalogV1 -- [title_catalog_updated](catalogv1/title-catalog-updated.md) +- [title_catalog_updated](CatalogV1/title-catalog-updated.md) This event is triggered when a catalog is changed. -- [title_store_updated](catalogv1/title-store-updated.md) +- [title_store_updated](CatalogV1/title-store-updated.md) This event is triggered when a store is changed. ## CatalogV2 @@ -347,93 +344,51 @@ Each event type has a set of properties that are included as part of event's dat ## Character -- [character_consumed_item](character-consumed-item.md) +- [character_consumed_item](Character/character-consumed-item.md) This event is triggered when a character consumes an item from their inventory. - -- [character_inventory_item_added](character-inventory-item-added.md) +- [character_inventory_item_added](Character/character-inventory-item-added.md) This event is triggered when an item is granted to a character. -- [character_vc_item_purchased](character-vc-item-purchased.md) +- [character_vc_item_purchased](Character/character-vc-item-purchased.md) This event is triggered when the character makes a purchase using virtual currency. -- [character_virtual_currency_balance_changed](character-virtual-currency-balance-changed.md) +- [character_virtual_currency_balance_changed](Character/character-virtual-currency-balance-changed.md) This event is triggered when a character's virtual currency balance changes. -## InventoryV1 +## Inventory -- [character_consumed_item](inventoryv1/character-consumed-item.md) - This event is triggered when a character consumes an item from their inventory. - -- [character_inventory_item_added](inventoryv1/character-inventory-item-added.md) - This event is triggered when an item is granted to a character. - -- [character_vc_item_purchased](inventoryv1/character-vc-item-purchased.md) - This event is triggered when the character makes a purchase using virtual currency. - -- [character_virtual_currency_balance_changed](inventoryv1/character-virtual-currency-balance-changed.md) - This event is triggered when a character's virtual currency balance changes. - -- [player_consumed_item](inventoryv1/player-consumed-item.md) - This event is triggered when a player consumes an item from their inventory. - -- [player_inventory_item_added](inventoryv1/player-inventory-item-added.md) - This event is triggered when an item is granted to a player. - -- [player_paid_for_purchase](inventoryv1/player-paid-for-purchase.md) - This event is triggered when the second step of the payment process completes, paying for the purchase. - -- [player_realmoney_purchase](inventoryv1/player-realmoney-purchase.md) - This event is triggered when a player makes a real money purchase, and generates revenue for the game. - -- [player_receipt_validation](inventoryv1/player-receipt-validation.md) - This event is triggered when a player attempts to make a real money purchase and the purchase receipt is being validated. - -- [player_redeemed_coupon](inventoryv1/player-redeemed-coupon.md) - This event is triggered when a player redeems a coupon. - -- [player_started_purchase](inventoryv1/player-started-purchase.md) - This event is triggered when a player starts a purchase. - -- [player_vc_item_purchased](inventoryv1/player-vc-item-purchased.md) - This event is triggered when the player makes a purchase using virtual currency. - -- [player_virtual_currency_balance_changed](inventoryv1/player-virtual-currency-balance-changed.md) - This event is triggered when a player's virtual currency balance changes. - -## InventoryV2 - -- [items_added](inventoryv2/items-added.md) +- [items_added](Inventory/items-added.md) Event raised when items have been added to an inventory. -- [items_clawback_completed](inventoryv2/items-clawback-completed.md) +- [items_clawback_completed](Inventory/items-clawback-completed.md) This event is triggered when an items clawback operation is completed. -- [items_clawback_reversal_completed](inventoryv2/items-clawback-reversal-completed.md) +- [items_clawback_reversal_completed](Inventory/items-clawback-reversal-completed.md) This event is triggered when an items clawback reversal operation is completed. -- [items_deleted](inventoryv2/items-deleted.md) +- [items_deleted](Inventory/items-deleted.md) Event raised when items have been deleted from an inventory. -- [items_expired](inventoryv2/items-expired.md) +- [items_expired](Inventory/items-expired.md) This event is triggered when items have expired in an inventory. -- [items_purchased](inventoryv2/items-purchased.md) +- [items_purchased](Inventory/items-purchased.md) Event raised when items have been purchased from an inventory. -- [items_redeemed](inventoryv2/items-redeemed.md) +- [items_redeemed](Inventory/items-redeemed.md) Event raised when items have been redeemed to an inventory. -- [items_subtracted](inventoryv2/items-subtracted.md) +- [items_subtracted](Inventory/items-subtracted.md) Event raised when items have been subtracted from an inventory. -- [items_transferred](inventoryv2/items-transferred.md) +- [items_transferred](Inventory/items-transferred.md) Event raised when items have been transferred to or from an inventory. -- [items_updated](inventoryv2/items-updated.md) +- [items_updated](Inventory/items-updated.md) Event raised when items have been updated in an inventory. -- [marketplace_transaction_redeemed](inventoryv2/marketplace-transaction-redeemed.md) +- [marketplace_transaction_redeemed](Inventory/marketplace-transaction-redeemed.md) This event is triggered when a marketplace transaction is redeemed. ## GameSave @@ -446,50 +401,50 @@ Each event type has a set of properties that are included as part of event's dat ## Partner -- [display_name_filtered](display-name-filtered.md) +- [display_name_filtered](Partner/display-name-filtered.md) This event is triggered when a display name is filtered by community sift. -- [player_display_name_filtered](player-display-name-filtered.md) +- [player_display_name_filtered](Partner/player-display-name-filtered.md) This event is triggered when a display name is filtered by community sift only if there is an associated player EntityId for the event. -- [player_photon_session_authenticated](player-photon-session-authenticated.md) +- [player_photon_session_authenticated](Partner/player-photon-session-authenticated.md) This event is triggered when a player connects to a Photon Cloud application and authenticates with PlayFab using Photon custom authentication. ## Player -- [player_action_executed](player-action-executed.md) +- [player_action_executed](Player/player-action-executed.md) This event is triggered when an action linked to a segmentation change or event rule executes on a player. -- [player_ad_campaign_attribution](player-ad-campaign-attribution.md) +- [player_ad_campaign_attribution](Player/player-ad-campaign-attribution.md) This event is triggered by an attribution tracking Add-on when a player is matched to a paid acquisition campaign. -- [player_consumed_item](player-consumed-item.md) +- [player_consumed_item](Player/player-consumed-item.md) This event is triggered when a player consumes an item from their inventory. -- [player_inventory_item_added](player-inventory-item-added.md) +- [player_inventory_item_added](Player/player-inventory-item-added.md) This event is triggered when an item is granted to a player. -- [player_paid_for_purchase](player-paid-for-purchase.md) +- [player_paid_for_purchase](Player/player-paid-for-purchase.md) This event is triggered when the second step of the payment process completes, paying for the purchase. -- [player_realmoney_purchase](player-realmoney-purchase.md) +- [player_realmoney_purchase](Player/player-realmoney-purchase.md) This event is triggered when a player makes a real money purchase, and generates revenue for the game. -- [player_receipt_validation](player-receipt-validation.md) +- [player_receipt_validation](Player/player-receipt-validation.md) This event is triggered when a player attempts to make a real money purchase and the purchase receipt is being validated. -- [player_redeemed_coupon](player-redeemed-coupon.md) +- [player_redeemed_coupon](Player/player-redeemed-coupon.md) This event is triggered when a player redeems a coupon. -- [player_set_profile_property](player-set-profile-property.md) +- [player_set_profile_property](Player/player-set-profile-property.md) This event is triggered when PlayFab makes an internal adjustment to a player profile. -- [player_started_purchase](player-started-purchase.md) +- [player_started_purchase](Player/player-started-purchase.md) This event is triggered when a player starts a purchase. -- [player_vc_item_purchased](player-vc-item-purchased.md) +- [player_vc_item_purchased](Player/player-vc-item-purchased.md) This event is triggered when the player makes a purchase using virtual currency. -- [player_virtual_currency_balance_changed](player-virtual-currency-balance-changed.md) +- [player_virtual_currency_balance_changed](Player/player-virtual-currency-balance-changed.md) This event is triggered when a player's virtual currency balance changes. ## PlayerIdentity @@ -621,32 +576,26 @@ Each event type has a set of properties that are included as part of event's dat ## Session -- [client_focus_change](client-focus-change.md) +- [client_focus_change](Session/client-focus-change.md) This event is triggered every time the application enters or exits focus on the player's device. -- [client_session_start](client-session-start.md) +- [client_session_start](Session/client-session-start.md) This event is triggered when a new client session starts. ## Title -- [title_catalog_updated](title-catalog-updated.md) - This event is triggered when a catalog is changed. - -- [title_client_rate_limited_alert](title-client-rate-limited-alert.md) +- [title_client_rate_limited_alert](Title/title-client-rate-limited-alert.md) This event is triggered when a single IP address generates too many API calls to PlayFab and is throttled. -- [title_high_error_rate_alert](title-high-error-rate-alert.md) +- [title_high_error_rate_alert](Title/title-high-error-rate-alert.md) This event is triggered when a game title experiences a high rate of errors. -- [title_requested_limit_change](title-requested-limit-change.md) +- [title_requested_limit_change](Title/title-requested-limit-change.md) This event is triggered when a title requests a service limit change. -- [title_saved_survey](title-saved-survey.md) +- [title_saved_survey](Title/title-saved-survey.md) This event is triggered when a game's survey is saved. -- [title_store_updated](title-store-updated.md) - This event is triggered when a store is changed. - ## TitleData - [title_news_updated](TitleData/title-news-updated.md) diff --git a/playfab-docs/api-references/toc.yml b/playfab-docs/api-references/toc.yml index eee939f01..38e494193 100644 --- a/playfab-docs/api-references/toc.yml +++ b/playfab-docs/api-references/toc.yml @@ -22,311 +22,440 @@ items: - name: Model reference href: events/index.md + - name: AdPlacement + items: + - name: player_ad_closed + href: events/AdPlacement/player-ad-closed.md + - name: player_ad_ended + href: events/AdPlacement/player-ad-ended.md + - name: player_ad_opened + href: events/AdPlacement/player-ad-opened.md + - name: player_ad_rewarded + href: events/AdPlacement/player-ad-rewarded.md + - name: player_ad_started + href: events/AdPlacement/player-ad-started.md + - name: Addons + items: + - name: title_addon_changed + href: events/Addons/title-addon-changed.md + - name: ApiAccessPolicy + items: + - name: title_api_settings_changed + href: events/ApiAccessPolicy/title-api-settings-changed.md + - name: title_permission_policy_changed + href: events/ApiAccessPolicy/title-permission-policy-changed.md + - name: CloudScript items: - - name: auth_token_validated - href: events/auth-token-validated.md - - name: character_consumed_item - href: events/character-consumed-item.md - - name: character_created - href: events/character-created.md - - name: character_inventory_item_added - href: events/character-inventory-item-added.md - - name: character_statistic_changed - href: events/Leaderboards/character-statistic-changed.md - - name: character_statistic_deleted - href: events/Leaderboards/character-statistic-deleted.md - - name: character_vc_item_purchased - href: events/character-vc-item-purchased.md - - name: character_virtual_currency_balance_changed - href: events/character-virtual-currency-balance-changed.md - - name: client_focus_change - href: events/client-focus-change.md - - name: client_session_start - href: events/client-session-start.md - - name: entity_created - href: events/entity-created.md - name: entity_executed_cloud_script - href: events/entity-executed-cloud-script.md - - name: entity_files_set - href: events/entity-files-set.md - - name: entity_language_updated - href: events/entity-language-updated.md - - name: entity_logged_in - href: events/entity-logged-in.md - - name: entity_objects_set - href: events/entity-objects-set.md - - name: entity_virtual_currency_balances_changed - href: events/entity-virtual-currency-balances-changed.md + href: events/CloudScript/entity-executed-cloud-script.md + - name: player_executed_cloudscript + href: events/CloudScript/player-executed-cloudscript.md + - name: player_triggered_action_executed_cloudscript + href: events/CloudScript/player-triggered-action-executed-cloudscript.md + - name: title_added_cloudscript + href: events/CloudScript/title-added-cloudscript.md + - name: title_published_cloudscript + href: events/CloudScript/title-published-cloudscript.md + - name: title_scheduled_cloudscript_executed + href: events/CloudScript/title-scheduled-cloudscript-executed.md + - name: cloudscript_executed + href: events/CloudScript/cloudscript-executed.md + - name: DeveloperIdentity + items: + - name: studio_created + href: events/DeveloperIdentity/studio-created.md + - name: studio_user_added + href: events/DeveloperIdentity/studio-user-added.md + - name: studio_user_invited + href: events/DeveloperIdentity/studio-user-invited.md + - name: studio_user_removed + href: events/DeveloperIdentity/studio-user-removed.md + - name: Extension + items: + - name: title_aborted_task + href: events/Extension/title-aborted-task.md + - name: title_completed_task + href: events/Extension/title-completed-task.md + - name: title_created_task + href: events/Extension/title-created-task.md + - name: title_deleted_task + href: events/Extension/title-deleted-task.md + - name: title_exceeded_limit + href: events/Extension/title-exceeded-limit.md + - name: title_limit_changed + href: events/Extension/title-limit-changed.md + - name: title_started_task + href: events/Extension/title-started-task.md + - name: title_updated_task + href: events/Extension/title-updated-task.md + - name: export_completed + href: events/Extension/export-completed.md + - name: Functions + items: + - name: function_executed + href: events/Functions/function-executed.md + - name: function_registered + href: events/Functions/function-registered.md + - name: function_unregistered + href: events/Functions/function-unregistered.md + - name: player_triggered_action_executed_function + href: events/Functions/player-triggered-action-executed-function.md + - name: title_scheduled_function_executed + href: events/Functions/title-scheduled-function-executed.md + - name: Groups + items: - name: group_created - href: events/group-created.md - - name: group_deleted - href: events/group-deleted.md + href: events/Groups/group-created.md - name: group_members_added - href: events/group-members-added.md + href: events/Groups/group-members-added.md - name: group_members_removed - href: events/group-members-removed.md + href: events/Groups/group-members-removed.md - name: group_role_created - href: events/group-role-created.md + href: events/Groups/group-role-created.md - name: group_role_deleted - href: events/group-role-deleted.md + href: events/Groups/group-role-deleted.md - name: group_role_members_added - href: events/group-role-members-added.md + href: events/Groups/group-role-members-added.md - name: group_role_members_removed - href: events/group-role-members-removed.md + href: events/Groups/group-role-members-removed.md - name: group_role_updated - href: events/group-role-updated.md + href: events/Groups/group-role-updated.md - name: group_updated - href: events/group-updated.md - - name: item_created - href: events/item-created.md - - name: item_deleted - href: events/item-deleted.md - - name: item_moderation_state_changed - href: events/item-moderation-state-changed.md - - name: item_publish_requested - href: events/item-publish-requested.md - - name: item_reported - href: events/item-reported.md - - name: item_updated - href: events/item-updated.md - - name: items_added - href: events/items-added.md - - name: items_deleted - href: events/items-deleted.md - - name: items_purchased - href: events/items-purchased.md - - name: items_redeemed - href: events/items-redeemed.md - - name: items_subtracted - href: events/items-subtracted.md - - name: items_transferred - href: events/items-transferred.md - - name: items_updated - href: events/items-updated.md - - name: matchmaking_match_found - href: events/matchmaking-match-found.md - - name: matchmaking_ticket_completed - href: events/matchmaking-ticket-completed.md - - name: matchmaking_user_ticket_completed - href: events/matchmaking-user-ticket-completed.md - - name: matchmaking_user_ticket_invite - href: events/matchmaking-user-ticket-invite.md + href: events/Groups/group-updated.md + - name: members_added + href: events/Groups/members-added.md + - name: members_removed + href: events/Groups/members-removed.md + - name: members_role_updated + href: events/Groups/members-role-updated.md + - name: player_updated_membership + href: events/Groups/player-updated-membership.md + - name: role_updated + href: events/Groups/role-updated.md + - name: Telemetry + items: + - name: apikey_activated + href: events/Telemetry/apikey-activated.md + - name: apikey_created + href: events/Telemetry/apikey-created.md + - name: apikey_deactivated + href: events/Telemetry/apikey-deactivated.md + - name: apikey_deleted + href: events/Telemetry/apikey-deleted.md + - name: TitleCommunications + items: + - name: player_registered_push_notifications + href: events/TitleCommunications/player-registered-push-notifications.md + - name: sent_email + href: events/TitleCommunications/sent-email.md + - name: sent_push_notification + href: events/TitleCommunications/sent-push-notification.md + - name: email_sent + href: events/TitleCommunications/email-sent.md + - name: push_notification_sent + href: events/TitleCommunications/push-notification-sent.md + - name: General + items: + - name: entity_virtual_currency_balances_changed + href: events/General/entity-virtual-currency-balances-changed.md + - name: tenancy_connector_onboard + href: events/General/tenancy-connector-onboard.md + - name: studio_tier_updated + href: events/General/studio-tier-updated.md + - name: Matchmaking + items: + - name: title_queue_config_updated + href: events/Matchmaking/title-queue-config-updated.md + - name: match_found + href: events/Matchmaking/match-found.md + - name: ticket_completed + href: events/Matchmaking/ticket-completed.md + - name: user_ticket_invited + href: events/Matchmaking/user-ticket-invited.md + - name: Multiplayer Servers + items: - name: build_alias_created - href: events/build-alias-created.md + href: events/MultiplayerServers/build-alias-created.md - name: build_alias_deleted - href: events/build-alias-deleted.md + href: events/MultiplayerServers/build-alias-deleted.md - name: build_alias_updated - href: events/build-alias-updated.md + href: events/MultiplayerServers/build-alias-updated.md - name: build_deleted - href: events/build-deleted.md + href: events/MultiplayerServers/build-deleted.md - name: build_region_status_changed - href: events/build-region-status-changed.md + href: events/MultiplayerServers/build-region-status-changed.md - name: build_region_updated - href: events/build-region-updated.md + href: events/MultiplayerServers/build-region-updated.md - name: build_region_utilization - href: events/build-region-utilization.md + href: events/MultiplayerServers/build-region-utilization.md - name: certificate_deleted - href: events/certificate-deleted.md + href: events/MultiplayerServers/certificate-deleted.md - name: certificate_uploaded - href: events/certificate-uploaded.md + href: events/MultiplayerServers/certificate-uploaded.md - name: crash_detected - href: events/crash-detected.md + href: events/MultiplayerServers/crash-detected.md - name: create_build_initiated - href: events/create-build-initiated.md + href: events/MultiplayerServers/create-build-initiated.md - name: enabled_for_title - href: events/enabled-for-title.md - - name: game_asset_deleted - href: events/game-asset-deleted.md - - name: monitoring_output_saved - href: events/monitoring-output-saved.md + href: events/MultiplayerServers/enabled-for-title.md + - name: game_asset_deleted + href: events/MultiplayerServers/game-asset-deleted.md + - name: monitoring_output_saved + href: events/MultiplayerServers/monitoring-output-saved.md - name: secret_added - href: events/secret-added.md + href: events/MultiplayerServers/secret-added.md - name: secret_deleted - href: events/secret-deleted.md - - name: server_requested - href: events/server-requested.md - - name: server_state_changed - href: events/server-state-changed.md - - name: vm_assigned - href: events/vm-assigned.md + href: events/MultiplayerServers/secret-deleted.md + - name: server_requested + href: events/MultiplayerServers/server-requested.md + - name: server_state_changed + href: events/MultiplayerServers/server-state-changed.md + - name: vm_assigned + href: events/MultiplayerServers/vm-assigned.md - name: vm_game_certificates_deployed - href: events/vm-game-certificates-deployed.md - - name: vm_remote_user_created - href: events/vm-remote-user-created.md - - name: vm_remote_user_deleted - href: events/vm-remote-user-deleted.md - - name: vm_unassignment_started - href: events/vm-unassignment-started.md + href: events/MultiplayerServers/vm-game-certificates-deployed.md + - name: vm_remote_user_created + href: events/MultiplayerServers/vm-remote-user-created.md + - name: vm_remote_user_deleted + href: events/MultiplayerServers/vm-remote-user-deleted.md + - name: vm_state_change + href: events/MultiplayerServers/vm-state-change.md + - name: vm_unassignment_started + href: events/MultiplayerServers/vm-unassignment-started.md - name: vm_unhealthy - href: events/vm-unhealthy.md - - name: player_action_executed - href: events/player-action-executed.md - - name: player_ad_activity_valued - href: events/player-ad-activity-valued.md - - name: player_ad_campaign_attribution - href: events/player-ad-campaign-attribution.md - - name: player_ad_closed - href: events/player-ad-closed.md - - name: player_ad_ended - href: events/player-ad-ended.md - - name: player_ad_opened - href: events/player-ad-opened.md - - name: display_name_filtered - href: events/display-name-filtered.md - - name: player_ad_rewarded - href: events/player-ad-rewarded.md - - name: player_ad_started - href: events/player-ad-started.md - - name: player_added_title - href: events/player-added-title.md - - name: player_banned - href: events/player-banned.md - - name: player_changed_avatar - href: events/player-changed-avatar.md - - name: player_completed_password_reset - href: events/player-completed-password-reset.md - - name: player_consumed_item - href: events/player-consumed-item.md - - name: player_created - href: events/player-created.md - - name: player_data_exported - href: events/player-data-exported.md - - name: player_device_info - href: events/player-device-info.md - - name: player_display_name_filtered - href: events/player-display-name-filtered.md - - name: player_displayname_changed - href: events/player-displayname-changed.md - - name: player_executed_cloudscript - href: events/player-executed-cloudscript.md - - name: player_inventory_item_added - href: events/player-inventory-item-added.md - - name: player_linked_account - href: events/player-linked-account.md - - name: player_logged_in - href: events/player-logged-in.md - - name: player_profile_memberships - href: events/data-types/playermemberships.md - - name: player_profile_subscriptions - href: events/data-types/subscriptions.md - - name: player_paid_for_purchase - href: events/player-paid-for-purchase.md - - name: player_password_reset_link_sent - href: events/player-password-reset-link-sent.md - - name: player_photon_session_authenticated - href: events/player-photon-session-authenticated.md - - name: player_ranked_on_leaderboard_version + href: events/MultiplayerServers/vm-unhealthy.md + - name: CatalogV1 + items: + - name: title_catalog_updated + href: events/CatalogV1/title-catalog-updated.md + - name: title_store_updated + href: events/CatalogV1/title-store-updated.md + - name: CatalogV2 + items: + - name: item_created + href: events/CatalogV2/item-created.md + - name: item_deleted + href: events/CatalogV2/item-deleted.md + - name: item_moderation_state_changed + href: events/CatalogV2/item-moderation-state-changed.md + - name: item_publish_requested + href: events/CatalogV2/item-publish-requested.md + - name: item_reported + href: events/CatalogV2/item-reported.md + - name: item_updated + href: events/CatalogV2/item-updated.md + - name: review_reported + href: events/CatalogV2/review-reported.md + - name: reviews_takedown_requested + href: events/CatalogV2/reviews-takedown-requested.md + - name: Character + items: + - name: character_consumed_item + href: events/Character/character-consumed-item.md + - name: character_inventory_item_added + href: events/Character/character-inventory-item-added.md + - name: character_vc_item_purchased + href: events/Character/character-vc-item-purchased.md + - name: character_virtual_currency_balance_changed + href: events/Character/character-virtual-currency-balance-changed.md + - name: Inventory + items: + - name: items_added + href: events/Inventory/items-added.md + - name: items_clawback_completed + href: events/Inventory/items-clawback-completed.md + - name: items_clawback_reversal_completed + href: events/Inventory/items-clawback-reversal-completed.md + - name: items_deleted + href: events/Inventory/items-deleted.md + - name: items_expired + href: events/Inventory/items-expired.md + - name: items_purchased + href: events/Inventory/items-purchased.md + - name: items_redeemed + href: events/Inventory/items-redeemed.md + - name: items_subtracted + href: events/Inventory/items-subtracted.md + - name: items_transferred + href: events/Inventory/items-transferred.md + - name: items_updated + href: events/Inventory/items-updated.md + - name: marketplace_transaction_redeemed + href: events/Inventory/marketplace-transaction-redeemed.md + - name: GameSave + items: + - name: gamesave_version_finalized + href: events/GameSave/gamesave-version-finalized.md + - name: gamesave_version_marked_known_good + href: events/GameSave/gamesave-version-marked-known-good.md + - name: Partner + items: + - name: display_name_filtered + href: events/Partner/display-name-filtered.md + - name: player_display_name_filtered + href: events/Partner/player-display-name-filtered.md + - name: player_photon_session_authenticated + href: events/Partner/player-photon-session-authenticated.md + - name: Player + items: + - name: player_action_executed + href: events/Player/player-action-executed.md + - name: player_ad_campaign_attribution + href: events/Player/player-ad-campaign-attribution.md + - name: player_consumed_item + href: events/Player/player-consumed-item.md + - name: player_inventory_item_added + href: events/Player/player-inventory-item-added.md + - name: player_paid_for_purchase + href: events/Player/player-paid-for-purchase.md + - name: player_set_profile_property + href: events/Player/player-set-profile-property.md + - name: player_started_purchase + href: events/Player/player-started-purchase.md + - name: player_vc_item_purchased + href: events/Player/player-vc-item-purchased.md + - name: player_virtual_currency_balance_changed + href: events/Player/player-virtual-currency-balance-changed.md + - name: PlayerIdentity + items: + - name: auth_token_validated + href: events/PlayerIdentity/auth-token-validated.md + - name: character_created + href: events/PlayerIdentity/character-created.md + - name: entity_created + href: events/PlayerIdentity/entity-created.md + - name: entity_logged_in + href: events/PlayerIdentity/entity-logged-in.md + - name: player_added_title + href: events/PlayerIdentity/player-added-title.md + - name: player_banned + href: events/PlayerIdentity/player-banned.md + - name: player_changed_avatar + href: events/PlayerIdentity/player-changed-avatar.md + - name: player_completed_password_reset + href: events/PlayerIdentity/player-completed-password-reset.md + - name: player_created + href: events/PlayerIdentity/player-created.md + - name: player_data_exported + href: events/PlayerIdentity/player-data-exported.md + - name: player_device_info + href: events/PlayerIdentity/player-device-info.md + - name: player_displayname_changed + href: events/PlayerIdentity/player-displayname-changed.md + - name: player_linked_account + href: events/PlayerIdentity/player-linked-account.md + - name: player_logged_in + href: events/PlayerIdentity/player-logged-in.md + - name: player_password_reset_link_sent + href: events/PlayerIdentity/player-password-reset-link-sent.md + - name: player_removed_title + href: events/PlayerIdentity/player-removed-title.md + - name: player_reported_as_abusive + href: events/PlayerIdentity/player-reported-as-abusive.md + - name: player_tag_added + href: events/PlayerIdentity/player-tag-added.md + - name: player_tag_removed + href: events/PlayerIdentity/player-tag-removed.md + - name: player_unlinked_account + href: events/PlayerIdentity/player-unlinked-account.md + - name: player_updated_contact_email + href: events/PlayerIdentity/player-updated-contact-email.md + - name: player_verified_contact_email + href: events/PlayerIdentity/player-verified-contact-email.md + - name: title_deleted_master_player + href: events/PlayerIdentity/title-deleted-master-player.md + - name: title_initiated_player_password_reset + href: events/PlayerIdentity/title-initiated-player-password-reset.md + - name: title_profile_view_constraints_changed + href: events/PlayerIdentity/title-profile-view-constraints-changed.md + - name: entity_deleted + href: events/PlayerIdentity/entity-deleted.md + - name: logged_in_to_title + href: events/PlayerIdentity/logged-in-to-title.md + - name: player_authenticated + href: events/PlayerIdentity/player-authenticated.md + - name: player_custom_properties_changed + href: events/PlayerIdentity/player-custom-properties-changed.md + - name: player_identity_link_added + href: events/PlayerIdentity/player-identity-link-added.md + - name: player_identity_link_removed + href: events/PlayerIdentity/player-identity-link-removed.md + - name: player_updated_login_email + href: events/PlayerIdentity/player-updated-login-email.md + - name: PlayerProfile + items: + - name: entity_files_set + href: events/PlayerProfile/entity-files-set.md + - name: entity_language_updated + href: events/PlayerProfile/entity-language-updated.md + - name: entity_objects_set + href: events/PlayerProfile/entity-objects-set.md + - name: access_policy_updated + href: events/PlayerProfile/access-policy-updated.md + - name: avatar_url_updated + href: events/PlayerProfile/avatar-url-updated.md + - name: contact_email_updated + href: events/PlayerProfile/contact-email-updated.md + - name: files_changed + href: events/PlayerProfile/files-changed.md + - name: language_updated + href: events/PlayerProfile/language-updated.md + - name: objects_updated + href: events/PlayerProfile/objects-updated.md + - name: Session + items: + - name: client_focus_change + href: events/Session/client-focus-change.md + - name: client_session_start + href: events/Session/client-session-start.md + - name: Title + items: + - name: title_client_rate_limited_alert + href: events/Title/title-client-rate-limited-alert.md + - name: title_high_error_rate_alert + href: events/Title/title-high-error-rate-alert.md + - name: title_requested_limit_change + href: events/Title/title-requested-limit-change.md + - name: title_saved_survey + href: events/Title/title-saved-survey.md + - name: TitleData + items: + - name: title_news_updated + href: events/TitleData/title-news-updated.md + - name: title_secret_key_changed + href: events/TitleData/title-secret-key-changed.md + - name: title_activated + href: events/TitleData/title-activated.md + - name: title_data_override_deleted + href: events/TitleData/title-data-override-deleted.md + - name: title_data_updated + href: events/TitleData/title-data-updated.md + - name: title_deactivated + href: events/TitleData/title-deactivated.md + - name: Statistics + items: + - name: statistic_updated + href: events/Statistics/statistic-updated.md + - name: Leaderboards + items: + - name: character_statistic_changed + href: events/Leaderboards/character-statistic-changed.md + - name: character_statistic_deleted + href: events/Leaderboards/character-statistic-deleted.md + - name: entity_rank_on_leaderboard_version_ended + href: events/Leaderboards/entity-rank-on-leaderboard-version-ended.md + - name: leaderboard_version_ended + href: events/Leaderboards/leaderboard-version-ended.md + - name: player_ranked_on_leaderboard_version href: events/Leaderboards/player-ranked-on-leaderboard-version.md - - name: player_realmoney_purchase - href: events/player-realmoney-purchase.md - - name: player_receipt_validation - href: events/player-receipt-validation.md - - name: player_redeemed_coupon - href: events/player-redeemed-coupon.md - - name: player_registered_push_notifications - href: events/player-registered-push-notifications.md - - name: player_removed_title - href: events/player-removed-title.md - - name: player_reported_as_abusive - href: events/player-reported-as-abusive.md - - name: player_set_profile_property - href: events/player-set-profile-property.md - - name: player_started_purchase - href: events/player-started-purchase.md - - name: player_statistic_changed + - name: player_statistic_changed href: events/Leaderboards/player-statistic-changed.md - - name: player_statistic_deleted + - name: player_statistic_deleted href: events/Leaderboards/player-statistic-deleted.md - - name: player_tag_added - href: events/player-tag-added.md - - name: player_tag_removed - href: events/player-tag-removed.md - - name: player_triggered_action_executed_cloudscript - href: events/player-triggered-action-executed-cloudscript.md - - name: player_unlinked_account - href: events/player-unlinked-account.md - - name: player_updated_contact_email - href: events/player-updated-contact-email.md - - name: player_vc_item_purchased - href: events/player-vc-item-purchased.md - - name: player_verified_contact_email - href: events/player-verified-contact-email.md - - name: player_virtual_currency_balance_changed - href: events/player-virtual-currency-balance-changed.md - - name: review_reported - href: events/review-reported.md - - name: reviews_takedown_requested - href: events/reviews-takedown-requested.md - - name: sent_email - href: events/sent-email.md - - name: sent_push_notification - href: events/sent-push-notification.md - - name: studio_created - href: events/studio-created.md - - name: studio_tier_updated - href: events/studio-tier-updated.md - - name: studio_user_added - href: events/studio-user-added.md - - name: studio_user_invited - href: events/studio-user-invited.md - - name: studio_user_removed - href: events/studio-user-removed.md - - name: tenancy_connector_onboard - href: events/tenancy-connector-onboard.md - - name: title_aborted_task - href: events/title-aborted-task.md - - name: title_added_cloudscript - href: events/title-added-cloudscript.md - - name: title_api_settings_changed - href: events/title-api-settings-changed.md - - name: title_catalog_updated - href: events/title-catalog-updated.md - - name: title_client_rate_limited_alert - href: events/title-client-rate-limited-alert.md - - name: title_completed_task - href: events/title-completed-task.md - - name: title_created_task - href: events/title-created-task.md - - name: title_deleted - href: events/title-deleted.md - - name: title_deleted_master_player - href: events/title-deleted-master-player.md - - name: title_deleted_task - href: events/title-deleted-task.md - - name: title_exceeded_limit - href: events/title-exceeded-limit.md - - name: title_high_error_rate_alert - href: events/title-high-error-rate-alert.md - - name: title_initiated_player_password_reset - href: events/title-initiated-player-password-reset.md - - name: title_limit_changed - href: events/title-limit-changed.md - - name: title_news_updated - href: events/title-news-updated.md - - name: title_permission_policy_changed - href: events/title-permission-policy-changed.md - - name: title_profile_view_constraints_changed - href: events/title-profile-view-constraints-changed.md - - name: title_published_cloudscript - href: events/title-published-cloudscript.md - - name: title_queue_config_updated - href: events/title-queue-config-updated.md - - name: title_requested_limit_change - href: events/title-requested-limit-change.md - - name: title_saved_survey - href: events/title-saved-survey.md - - name: title_scheduled_cloudscript_executed - href: events/title-scheduled-cloudscript-executed.md - - name: title_secret_key_changed - href: events/title-secret-key-changed.md - - name: title_started_task - href: events/title-started-task.md - name: title_statistic_version_changed href: events/Leaderboards/title-statistic-version-changed.md - - name: title_store_updated - href: events/title-store-updated.md - - name: title_updated_task - href: events/title-updated-task.md + - name: title_statistic_deleted + href: events/Leaderboards/title-statistic-deleted.md - name: API access policy href: api-access-policy.md - name: Global API method error codes diff --git a/playfab-docs/community/leaderboards/leaderboards-with-playstream-and-telemetry.md b/playfab-docs/community/leaderboards/leaderboards-with-playstream-and-telemetry.md index c290be105..baa6d95d7 100644 --- a/playfab-docs/community/leaderboards/leaderboards-with-playstream-and-telemetry.md +++ b/playfab-docs/community/leaderboards/leaderboards-with-playstream-and-telemetry.md @@ -18,8 +18,8 @@ And if you want just the data analytics and warehousing without the real-time ev Leaderboards provides two optional events: -- [`playfab.leaderboard.leaderboard_version_ended`](../../api-references/events/leaderboard-version-ended.md) -- [`playfab.leaderboard.entity_rank_on_leaderboard_version_ended`](../../api-references/events/entity-rank-on-leaderboard-version-ended.md) +- [`playfab.leaderboard.leaderboard_version_ended`](../../api-references/events/Leaderboards/leaderboard-version-ended.md) +- [`playfab.leaderboard.entity_rank_on_leaderboard_version_ended`](../../api-references/events/Leaderboards/entity-rank-on-leaderboard-version-ended.md) These two events allow you to quickly know when a leaderboard version has ended and allow you to query previous data as soon as you want. With entity rank on leaderboard version ended, you can get the rank and score of the top entity for a leaderboard when that leaderboard version ended. @@ -51,8 +51,8 @@ For learning more about how to leverage these events to preform different action ## See Also -- [`playfab.leaderboard.leaderboard_version_ended`](../../api-references/events/leaderboard-version-ended.md) -- [`playfab.leaderboard.entity_rank_on_leaderboard_version_ended`](../../api-references/events/entity-rank-on-leaderboard-version-ended.md) +- [`playfab.leaderboard.leaderboard_version_ended`](../../api-references/events/Leaderboards/leaderboard-version-ended.md) +- [`playfab.leaderboard.entity_rank_on_leaderboard_version_ended`](../../api-references/events/Leaderboards/entity-rank-on-leaderboard-version-ended.md) - [PlayStream Overview](../../data-analytics/ingest-data/playstream-overview.md) - [Statistics with PlayStream and Telemetry](../../player-progression/statistics/statistics-with-playstream-and-telemetry.md). - [Telemetry Overview](../../data-analytics/ingest-data/telemetry-overview.md) diff --git a/playfab-docs/data-analytics/acting-data/action-rules-using-cloudscript-actions-with-playstream.md b/playfab-docs/data-analytics/acting-data/action-rules-using-cloudscript-actions-with-playstream.md index acc9104e2..7d93e6a3c 100644 --- a/playfab-docs/data-analytics/acting-data/action-rules-using-cloudscript-actions-with-playstream.md +++ b/playfab-docs/data-analytics/acting-data/action-rules-using-cloudscript-actions-with-playstream.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # Using CloudScript actions with PlayStream -When a CloudScript handler is launched from a PlayStream action, that handler has access to additional data on why it is being run - the *context* - which you can use to drive your server-side logic. +When a CloudScript handler is launched from a PlayStream action, that handler has access to more data on why It's being run - the *context* - which you can use to drive your server-side logic. This tutorial walks you through what all is available in the context, and how to make use of it in your CloudScript handlers. @@ -85,9 +85,9 @@ handlers.handlePlayStreamEventAndProfile = function (args, context) { In the case of a PlayStream-triggered CloudScript call, the context contains 3 elements that can be used to drive your server-authoritative handler's logic. -1. There’s the `playStreamEvent`, which you can see in the example code above. The `playStreamEvent` contains the complete event which triggered the handler as a JSON object, with all the parameters you see in the [PlayStream event documentation](../../api-references/events/index.md). So for example, if you set up a rule in your title that called `handlePlayStreamEventAndProfile` on any `player_logged_in event`, `playStreamEvent.EventName` would be `player_logged_in`, etc. ([here’s the complete set of parameters for that event](../../api-references/events/player-logged-in.md)). +1. There’s the `playStreamEvent`, which you can see in the example code above. The `playStreamEvent` contains the complete event which triggered the handler as a JSON object, with all the parameters you see in the [PlayStream event documentation](../../api-references/events/index.md). So for example, if you set up a rule in your title that called `handlePlayStreamEventAndProfile` on any `player_logged_in event`, `playStreamEvent.EventName` would be `player_logged_in`, etc. ([here’s the complete set of parameters for that event](../../api-references/events/PlayerIdentity/player-logged-in.md)). -1. Next, there’s the `playerProfile`, also shown in the previous example. This contains information about the player that triggered the event. You can find all the details of the profile parameters here, but among other things, it contains the complete set of statistics for the player in your title, as well as any custom tags you have assigned to the player, so that you can use that data for very rich decision-making. +1. Next, there’s the `playerProfile`, also shown in the previous example. This contains information about the player that triggered the event. You can find all the details of the profile parameters here, but among other things, it contains the complete set of statistics for the player in your title, and any custom tags you have assigned to the player, so that you can use that data for rich decision-making. 1. The last element of context is `triggeredByTask`. Unlike the first two, which are set when using Rules and Segment Enter/Exit triggers, `triggeredByTask` is only applicable when the handler is running as a result of a task, whether manual or on a timer. It contains only two parameters: @@ -105,6 +105,6 @@ So *name* is the element you’ll want to use to use in your handler’s code fl In many ways, CloudScript handlers triggered by PlayStream actions have even more potential functionality than those triggered directly through calls to `ExecuteCloudScript`, since there’s a rich set of data made available via the context. -This gives you the ability to update your handlers post-launch with *additional* logic that makes use of elements of the event or player profile that you hadn’t originally anticipated, *without* needing to update your client code in any way. +This gives you the ability to update your handlers post-launch with *more* logic that makes use of elements of the event or player profile that you hadn’t originally anticipated, *without* needing to update your client code in any way. In addition, we’ll continue to make additions to the player profile in future updates of the PlayFab service, which will provide even *more* options for server-side logic. diff --git a/playfab-docs/data-analytics/ingest-data/playstream-events.md b/playfab-docs/data-analytics/ingest-data/playstream-events.md index dad5103fc..8290f63f0 100644 --- a/playfab-docs/data-analytics/ingest-data/playstream-events.md +++ b/playfab-docs/data-analytics/ingest-data/playstream-events.md @@ -45,5 +45,5 @@ In the following table, you can find examples of these two types of events. | | PlayFabGenerated Events | UserGenerated Events | | ----------- | ----------- | ----------- | -| Standard Schema | [player_logged_in](../../api-references/events/player-logged-in.md)
[entity_created](../../api-references/events/entity-created.md) | [client_focus_change](../../api-references/events/client-focus-change.md)
[client_session_start](../../api-references/events/client-session-start.md) | +| Standard Schema | [player_logged_in](../../api-references/events/PlayerIdentity/player-logged-in.md)
[entity_created](../../api-references/events/PlayerIdentity/entity-created.md) | [client_focus_change](../../api-references/events/Session/client-focus-change.md)
[client_session_start](../../api-references/events/Session/client-session-start.md) | | Custom Schema | N/A | Free-style | diff --git a/playfab-docs/data-analytics/ingest-data/sessions.md b/playfab-docs/data-analytics/ingest-data/sessions.md index 75c7f1c25..19ed0308f 100644 --- a/playfab-docs/data-analytics/ingest-data/sessions.md +++ b/playfab-docs/data-analytics/ingest-data/sessions.md @@ -20,8 +20,8 @@ Session support is currently *only* available in Unity SDK. Support for our othe You'll need to have the **180829** version or newer. This SDK first introduces two new events that can be configured to be emitted from the client automatically: -1. [client_session_start](../../api-references/events/client-session-start.md) -2. [client_focus_change](../../api-references/events/client-focus-change.md) +1. [client_session_start](../../api-references/events/Session/client-session-start.md) +2. [client_focus_change](../../api-references/events/Session/client-focus-change.md) ## Logging and managing events diff --git a/playfab-docs/data-analytics/learn-data/trends/trends-overview.md b/playfab-docs/data-analytics/learn-data/trends/trends-overview.md index 5d67ee5d1..e913c0737 100644 --- a/playfab-docs/data-analytics/learn-data/trends/trends-overview.md +++ b/playfab-docs/data-analytics/learn-data/trends/trends-overview.md @@ -14,29 +14,29 @@ ms.localizationpriority: medium The Trends feature is a collection of graphical representations of game analytics key performance analytics (KPIs) metrics that acts as your gateway to valuable insights and strategic decision-making. -Simply navigate to the Dashboard section of the Analyze Tab in Game Manager to view industry–standard metrics about your game. +Navigate to the Dashboard section of the Analyze Tab in Game Manager to view industry–standard metrics about your game. -Trends allows you to evaluate daily historical performance across six KPIs including daily & monthly active players, new players, screentime, retention, and revenue. You can effortlessly compare different time periods from as short as one week to a full 6 months, enabling you to measure the impact of your efforts and make data-driven decisions. +Trends allow you evaluate daily historical performance across six KPIs including daily & monthly active players, new players, screen time, retention, and revenue. You can effortlessly compare different time periods from as short as one week to a full six months, enabling you to measure the impact of your efforts and make data-driven decisions. With the ability to break down KPIs by platform and region and segments as dimensions, you can identify top performers, focus on strategic markets, and uncover areas for improvement. ## Trends metrics **Active Players** -- **Daily Active Players (DAU)**: Number of unique players seen in the game per day based on the [player_logged_in](../../../api-references/events/player-logged-in.md) event. -- **Monthly Active Players (MAU) Rolling 30**: Number of unique players seen in the game during the span of the last 30 days based on the [player_logged_in event](../../../api-references/events/player-logged-in.md) event. +- **Daily Active Players (DAU)**: Number of unique players seen in the game per day based on the [player_logged_in](../../../api-references/events/PlayerIdentity/player-logged-in.md) event. +- **Monthly Active Players (MAU) Rolling 30**: Number of unique players seen in the game during the span of the last 30 days based on the [player_logged_in event](../../../api-references/events/PlayerIdentity/player-logged-in.md) event. **New Players** -- **New Players**: The number of players that were seen in the game for the first time based on the [player_added_title](../../../api-references/events/player-added-title.md) event. +- **New Players**: The number of players that were seen in the game for the first time based on the [player_added_title](../../../api-references/events/PlayerIdentity/player-added-title.md) event. **Screen Time** -- **Average Duration**: Average length of time that a player has the game on screen and in focus per day. This is based on the [client_focus_change](../../../api-references/events/client-focus-change.md) event. -- **Average On-Screen** Intervals: Average number of times a player has the game on screen and in focus per day. This is based on the [client_focus_change](../../../api-references/events/client-focus-change.md) event. +- **Average Duration**: Average length of time that a player has the game on screen and in focus per day. This is based on the [client_focus_change](../../../api-references/events/Session/client-focus-change.md) event. +- **Average On-Screen** Intervals: Average number of times a player has the game on screen and in focus per day. This is based on the [client_focus_change](../../../api-references/events/Session/client-focus-change.md) event. **New User Retention** -- **Nth Day New User Retention (Classical Retention)**: Percentage of players seen specifically on the Nth Day after they first played the game based on the [player_added_title](../../../api-references/events/player-added-title.md) and [player_logged_in](../../../api-references/events/player-logged-in.md) events. +- **Nth Day New User Retention (Classical Retention)**: Percentage of players seen specifically on the Nth Day after they first played the game based on the [player_added_title](../../../api-references/events/PlayerIdentity/player-added-title.md) and [player_logged_in](../../../api-references/events/PlayerIdentity/player-logged-in.md) events. **Transaction Revenue** -- **Revenue**: Total revenue (USD) per day generated from in-app purchases that use the PlayFab economy APIs. This is based on the [player_realmoney_purchase](../../../api-references/events/player-realmoney-purchase.md) event. +- **Revenue**: Total revenue (USD) per day generated from in-app purchases that use the PlayFab economy APIs. This is based on the [player_realmoney_purchase](../../../api-references/events/Player/player-realmoney-purchase.md) event. ## See also diff --git a/playfab-docs/data-analytics/privacy-compliance/gdpr-exporting-player-data.md b/playfab-docs/data-analytics/privacy-compliance/gdpr-exporting-player-data.md index 76fee5f1f..fd7ce46f4 100644 --- a/playfab-docs/data-analytics/privacy-compliance/gdpr-exporting-player-data.md +++ b/playfab-docs/data-analytics/privacy-compliance/gdpr-exporting-player-data.md @@ -41,7 +41,7 @@ This API immediately returns a `JobReceiptId`, which you should store in your re Upon completion of the export, an email containing the export download link will be sent to the notification email address configured for the title. -The completion of the task will also trigger a [`player_data_exported` PlayStream event](../../api-references/events/player-data-exported.md). The event contains the `JobReceiptId` as a property, as well as the `ExportDownloadUrl` property, which provides access to the exported data. Using either [Automation Rules with Azure Functions](../../live-service-management/service-gateway/automation/cloudscript-af/quickstart.md#azure-functions-in-automation-rules) or [Webhooks](../acting-data/webhooks-overview.md), you can register to receive these events on an endpoint of your choosing and process as needed. +The completion of the task will also trigger a [`player_data_exported` PlayStream event](../../api-references/events/PlayerIdentity/player-data-exported.md). The event contains the `JobReceiptId` as a property, as well as the `ExportDownloadUrl` property, which provides access to the exported data. Using either [Automation Rules with Azure Functions](../../live-service-management/service-gateway/automation/cloudscript-af/quickstart.md#azure-functions-in-automation-rules) or [Webhooks](../acting-data/webhooks-overview.md), you can register to receive these events on an endpoint of your choosing and process as needed. The following example is how to use the Admin API with the [C# SDK](../../sdks/c-sharp/index.md). If you would like to use a different SDK, select one from the list of [PlayFab SDKs](../../sdks/playfab-sdk-intro.md). diff --git a/playfab-docs/economy-monetization/economy/items/quickstart.md b/playfab-docs/economy-monetization/economy/items/quickstart.md index 0b3ea24b9..f88ef400b 100644 --- a/playfab-docs/economy-monetization/economy/items/quickstart.md +++ b/playfab-docs/economy-monetization/economy/items/quickstart.md @@ -105,6 +105,6 @@ To confirm the purchase in Game Manager: To confirm: -* Open the **PlayStream** tab. You should see a [Player virtual currency item purchased](../../../api-references/events/player-vc-item-purchased.md) event. +* Open the **PlayStream** tab. You should see a [Player virtual currency item purchased](../../../api-references/events/Player/player-vc-item-purchased.md) event. * Open the **Inventory** tab. The inventory should now contain an apple. You can also use features on the **Inventory** tab to revoke the item, or grant the player _more_ apples. * Open the **Virtual Currency** tab. The player should only have 95 gold left. diff --git a/playfab-docs/economy-monetization/economy/stores/quickstart.md b/playfab-docs/economy-monetization/economy/stores/quickstart.md index 6127c6aad..3c879b810 100644 --- a/playfab-docs/economy-monetization/economy/stores/quickstart.md +++ b/playfab-docs/economy-monetization/economy/stores/quickstart.md @@ -108,7 +108,7 @@ Open Game Manager, and confirm that the purchase was made at the store price of 3. Check the following information for the player: * Open the **Inventory** tab. The inventory should now contain a **pear**. * Open the **Virtual Currency** tab. Check the virtual currency **Amount** to verify that the player only spent 2 GD. - * Open the **PlayStream** tab. You'll see events showing the purchase flow from the store. Events include a [Player virtual currency item purchased](../../../api-references/events/player-vc-item-purchased.md) event, and a [Player virtual currency balance changed](../../../api-references/events/player-virtual-currency-balance-changed.md) event showing that the virtual currency balance changed by two GD. + * Open the **PlayStream** tab. You'll see events showing the purchase flow from the store. Events include a [Player virtual currency item purchased](../../../api-references/events/Player/player-vc-item-purchased.md) event, and a [Player virtual currency balance changed](../../../api-references/events/Player/player-virtual-currency-balance-changed.md) event showing that the virtual currency balance changed by two GD. > [!TIP] > You can use the Game Manager to change the order of items in your store and adjust prices at any time. diff --git a/playfab-docs/multiplayer/matchmaking/index.md b/playfab-docs/multiplayer/matchmaking/index.md index 06a433b02..29b4e3ae1 100644 --- a/playfab-docs/multiplayer/matchmaking/index.md +++ b/playfab-docs/multiplayer/matchmaking/index.md @@ -90,6 +90,6 @@ For more information on specific flows from either your game client or service, + [Matchmaking API Reference](xref:titleid.playfabapi.com.multiplayer.matchmaking) + [PlayStream Events](../../api-references/events/index.md) - + [matchmaking_match_found](../../api-references/events/matchmaking-match-found.md) - + [matchmaking_ticket_completed](../../api-references/events/matchmaking-ticket-completed.md) + + [matchmaking_match_found](../../api-references/events/Matchmaking/match-found.md) + + [matchmaking_ticket_completed](../../api-references/events/Matchmaking/ticket-completed.md) diff --git a/playfab-docs/player-progression/statistics/statistics-with-playstream-and-telemetry.md b/playfab-docs/player-progression/statistics/statistics-with-playstream-and-telemetry.md index e24d20018..4d014c181 100644 --- a/playfab-docs/player-progression/statistics/statistics-with-playstream-and-telemetry.md +++ b/playfab-docs/player-progression/statistics/statistics-with-playstream-and-telemetry.md @@ -34,7 +34,7 @@ Once you have enabled the event, you are now free to connect your events to what ## See Also -- [`playfab.statistic.statistic_updated`](../../api-references/events/statistic-updated.md) +- [`playfab.statistic.statistic_updated`](../../api-references/events/Statistics/statistic-updated.md) - [PlayStream Overview](../../data-analytics/ingest-data/playstream-overview.md) - [Leaderboards With PlayStream and Telemetry](../../community/leaderboards/leaderboards-with-playstream-and-telemetry.md) - [Telemetry Overview](../../data-analytics/ingest-data/telemetry-overview.md) diff --git a/playfab-docs/release-notes/2016.md b/playfab-docs/release-notes/2016.md index 84a440a88..d7974a669 100644 --- a/playfab-docs/release-notes/2016.md +++ b/playfab-docs/release-notes/2016.md @@ -6,7 +6,7 @@ ms.author: jenelleb ms.date: 07/12/2018 ms.topic: article ms.service: azure-playfab -keywords: playfab, development, release, apis, features +keywords: playfab, development, release, APIs, features ms.localizationpriority: medium --- @@ -14,13 +14,13 @@ ms.localizationpriority: medium ## 161121 -Date: 2016-11-20 +Date: November 20, 2016 ### API changes - Each Client API can now be individually enabled or disabled. - See our [blog post](https://blog.playfab.com/blog/permission-policies/) for details. -- We are releasing a new feature called Scheduled Tasks. +- We're releasing a new feature called Scheduled Tasks. - See our blog post for details: (Coming soon). ### New APIs @@ -41,34 +41,34 @@ Date: 2016-11-20 ### New PlayStream event -- [title_permission_policy_changed](../api-references/events/title-permission-policy-changed.md) +- [title_permission_policy_changed](../api-references/events/ApiAccessPolicy/title-permission-policy-changed.md) ### WindowsSDK specific changes -- A new overhauled **WindowsSDK** will be published next week. +- A new overhauled **WindowsSDK** is published next week. - See our blog post for a brief description. -- If you are interested in previewing the upcoming changes, post here: - - +- If you're interested in previewing the upcoming changes, post here: + - ## 161108 -Date: 2016-11-07 +Date: November 7, 2016 ### HOTFIX -Version 1.0 of the overhauled [CSharpSDK](https://github.com/PlayFab/CSharpSDK) increased the .Net version requirement from 4.0 to 4.6. This was not intended. This hotfix removes the 4.6 only features, so that it will once again build on .Net 4.0 or higher. +Version 1.0 of the overhauled [CSharpSDK](https://github.com/PlayFab/CSharpSDK) increased the .NET version requirement from 4.0 to 4.6. This isn't intended. This hotfix removes the 4.6 only features, so that it builds on .NET 4.0 or higher. ## 161107 -Date: 2016-11-06 +Date: November 6, 2016 ### API changes **Shared** - `CatalogItem` -- `InitialLimitedEditionCount` ( out of beta ) -If `IsLImitedEdition` is `true`, then this determines amount of the item initially available. Note that this field is ignored if the catalog item already existed in this catalog, or the field is less than 1. +- `InitialLimitedEditionCount` (out of beta) +If `IsLImitedEdition` is `true`, then this determines amount of the item initially available. This field is ignored if the catalog item already existed in this catalog, or the field is less than 1. - Player display name uniqueness is now optional. - Player display name returned as Photon "Nickname" when players connect to Photon Cloud. @@ -94,47 +94,47 @@ If `IsLImitedEdition` is `true`, then this determines amount of the item initial ## 161031 -Date: 2016-10-30 +Date: October 30, 2016 -~~**Unreal Blueprints hotfix release**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**Unreal Blueprints hotfix release**~~ (UPDATED: This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~UnrealBlueprintSDK **upgrade warning**: There was a naming conflict between Android and the PlayFab "SourceType" enum. As a result, we've had to rename this blueprint-enum. This breaks any [Client/GetStoreItems](xref:titleid.playfabapi.com.client.title-widedatamanagement.getstoreitems) or [Admin/GetStoreItems](xref:titleid.playfabapi.com.admin.title-widedatamanagement.getstoreitems) PlayFab-api-nodes. The upgrade process in-editor is to delete and re-create each affected blueprint node.~~ - ~~UnrealBlueprintSDK Specific Changes:~~ - - ~~Fixed a minor bug where certain errors would not report correctly~~ + - ~~Fixed a minor bug where certain errors wouldn't report correctly~~ - ~~Fixed a name conflict that prevented making Android builds (ESourceType)~~ ## 161017 -Date: 2016-10-16 +Date: October 16, 2016 ### Deprecation changes -- `Client/GetUserCombinedInfo` has transitioned from `Proposed` to `Deprecated`, which means most SDKs using this will now throw an error. Please transition to [Client/GetPlayerCombinedInfo](xref:titleid.playfabapi.com.client.accountmanagement.getplayercombinedinfo). -- Deprecated APIs from this patch note: [160822](#160822) have transitioned from deprecated to obsolete, according to this blog: [Deprecation Visibility](https://playfab.com/blog/deprecation-visibility/) and thus, those APIs have been removed from the newest version of the SDKs. If you update your SDK, you must now transition to the new replacement APIs. -- `Password` in the `Admin UserCredentials` object has been deprecated. You no longer need to know your user's password to call the `Admin/ResetUsers` method. +- `Client/GetUserCombinedInfo` has transitioned from `Proposed` to `Deprecated`, which means most SDKs using this will now throw an error. Transition to [Client/GetPlayerCombinedInfo](xref:titleid.playfabapi.com.client.accountmanagement.getplayercombinedinfo). +- Deprecated APIs from this patch note: [160822](#160822) transitioned from deprecated to obsolete, according to this blog: [Deprecation Visibility](https://playfab.com/blog/deprecation-visibility/) and thus, those APIs were removed from the newest version of the SDKs. If you update your SDK, you must now transition to the new replacement APIs. +- `Password` in the `Admin UserCredentials` object is deprecated. You no longer need to know your user's password to call the `Admin/ResetUsers` method. ### UnitySdk breaking changes - [UnitySdk](https://github.com/PlayFab/UnitySDK) - - If you are using reflection on PlayFab API-model types, you will have to convert your reflection logic from properties to fields (See UnitySdk Specific Changes below). + - If you're using reflection on PlayFab API-model types, you have to convert your reflection logic from properties to fields (See UnitySdk Specific Changes in the following section). ### API changes - **New PlayStream events:** - ~~`gamelobby_started`~~ (UPDATED: This is deprecated. See [Lobby-Matchmaking-Notifications](../multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md)) - ~~`gamelobby_ended`~~(UPDATED: This is deprecated. See [Lobby-Matchmaking-Notifications](../multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md)) - - [Client/AttributeInstall](xref:titleid.playfabapi.com.client.advertising.attributeinstall) request has deprecated `Android_Id` and converted to `Adid`. All SDKs have had some internal login hooks updated to account for this. This is not a breaking change, because it was always intended to use Google-AdvertisingId (Adid), and using the Android DeviceId here would not have worked properly. This change is merely for clarity and consistency - - For the GitHub add-on, revisions to CloudScript will no longer immediately go live. Instead a new revision will be made, and you make it live via Game Manager + - [Client/AttributeInstall](xref:titleid.playfabapi.com.client.advertising.attributeinstall) request deprecated `Android_Id` and converted to `Adid`. All SDKs had some internal login hooks updated to account for this. This isn't a breaking change, because it's intended to use Google-AdvertisingId (Adid), and using the Android DeviceId here doesn't work properly. This change is for clarity and consistency + - For the GitHub add-on, revisions to CloudScript no longer immediately go live. Instead a new revision is made, and you make it live via Game Manager - The default `helloWorld` CloudScript function described in this doc: [CloudScript quickstart](../live-service-management/service-gateway/automation/cloudscript/quickstart.md) was out of date. Updated the document to more closely match the current version (This is only relevant to new title creation) ### API Server bug fixes -- Fixed a 500 error in [Server/ExecuteCloudScript](xref:titleid.playfabapi.com.server.server-sidecloudscript.executecloudscript): PlayFabId is now a mandatory parameter (Formerly it would error if it wasn't provided) -- Fixed a 500 error in [Server/GetSharedGroupData](xref:titleid.playfabapi.com.server.sharedgroupdata.getsharedgroupdata): SharedGroupId is now a mandatory parameter (Formerly it would error if it wasn't provided) -- Fixed a 500 error in [Server/AddSharedGroupMembers](xref:titleid.playfabapi.com.server.sharedgroupdata.addsharedgroupmembers): PlayFabIds is now a mandatory parameter (Formerly it would error if it wasn't provided) -- Fixed a 500 error in [Server/RemoveSharedGroupMembers](xref:titleid.playfabapi.com.server.sharedgroupdata.removesharedgroupmembers): PlayFabIds is now a mandatory parameter (Formerly it would error if it wasn't provided) -- Fixed a 500 error in [Server/DeleteSharedGroup](xref:titleid.playfabapi.com.server.sharedgroupdata.deletesharedgroup): SharedGroupId is now a mandatory parameter (Formerly it would error if it wasn't provided) +- Fixed a 500 error in [Server/ExecuteCloudScript](xref:titleid.playfabapi.com.server.server-sidecloudscript.executecloudscript): PlayFabId is now a mandatory parameter. Formerly, the API threw an error if the PlayFabId wasn't provided. +- Fixed a 500 error in [Server/GetSharedGroupData](xref:titleid.playfabapi.com.server.sharedgroupdata.getsharedgroupdata): SharedGroupId is now a mandatory parameter. Formerly, the API threw an error if the SharedGroupId wasn't provided. +- Fixed a 500 error in [Server/AddSharedGroupMembers](xref:titleid.playfabapi.com.server.sharedgroupdata.addsharedgroupmembers): PlayFabIds is now a mandatory parameter. Formerly, the API threw an error if the PlayFabIds wasn't provided. +- Fixed a 500 error in [Server/RemoveSharedGroupMembers](xref:titleid.playfabapi.com.server.sharedgroupdata.removesharedgroupmembers): PlayFabIds is now a mandatory parameter. Formerly, the API threw an error if the PlayFabIds wasn't provided. +- Fixed a 500 error in [Server/DeleteSharedGroup](xref:titleid.playfabapi.com.server.sharedgroupdata.deletesharedgroup): SharedGroupId is now a mandatory parameter. Formerly, the API threw an error if the SharedGroupId wasn't provided. ### LuaSDK specific changes @@ -144,9 +144,9 @@ Date: 2016-10-16 ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - Model properties have been converted to fields so they display better in the Unity Inspector (where relevant). - - Fixed a bug where if a CloudScript function returns a primitive, it will now be properly deserialized and returned as FunctionResult (Formerly it would have been null). - - The PaperTrail package has been fixed: [UnityPlayFabPaperTrail.unitypackage](https://github.com/PlayFab/UnitySDK/blob/master/Packages/UnityPlayFabPaperTrail.unitypackage) + - Converted model properties to fields so they display better in the Unity Inspector (where relevant). + - Fixed a bug where if a CloudScript function returns a primitive, it's now properly deserialized and returned as FunctionResult. Formerly it's null. + - Fixed the PaperTrail package: [UnityPlayFabPaperTrail.unitypackage](https://github.com/PlayFab/UnitySDK/blob/master/Packages/UnityPlayFabPaperTrail.unitypackage) ### SDKGenerator specific changes @@ -155,7 +155,7 @@ Date: 2016-10-16 ## 161003 -Date: 2016-10-02 +Date: October 2, 2016 ### API changes @@ -183,26 +183,26 @@ Date: 2016-10-02 ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - [UnitySDK](https://github.com/PlayFab/UnitySDK) V0 repository is being retired. Everybody should please update to UnitySDK V2 available on our download page. - - `IDFA` and `AdvertisingId` will work properly on Unity 5.5 beta versions. - - CloudScript functions that return a primitive, such as an integer, will now deserialize correctly - - Minor improvements to Unity Compression, it should now be safe to enable compression in the PlayFabSharedSettings scriptable object. + - [UnitySDK](https://github.com/PlayFab/UnitySDK) V0 repository is being retired. Everybody should update to UnitySDK V2 available on our download page. + - `IDFA` and `AdvertisingId` work properly on Unity 5.5 beta versions. + - CloudScript functions that return a primitive, such as an integer, deserialize correctly + - Minor improvements to Unity Compression. It's now safe to enable compression in the PlayFabSharedSettings scriptable object. ### WindowsSDK specific problems - The .lib files published with this repo are now bigger than the GitHub max file-size limit. -- The latest version does not have updated lib files, and we've begun looking at alternatives. +- The latest version doesn't have updated lib files, and we've begun looking at alternatives. ## 160919 -Date: 2016-09-18 +Date: September 18, 2016 ### New APIs for payments -- We are expanding our Payments API to include a standard way to refund and dispute purchases. +- We're expanding our Payments API to include a standard way to refund and dispute purchases. - [Admin/RefundPurchase](xref:titleid.playfabapi.com.admin.playerdatamanagement.refundpurchase) - [Admin/ResolvePurchaseDispute](xref:titleid.playfabapi.com.admin.playerdatamanagement.resolvepurchasedispute) -**A few friend-based APIs have been copied from the Client to the Server:** +**Copied a few friend-based APIs from the Client to the Server:** - [Server/GetFriendLeaderboard](xref:titleid.playfabapi.com.server.playerdatamanagement.getfriendleaderboard) - [Server/AddFriend](xref:titleid.playfabapi.com.server.friendlistmanagement.addfriend) @@ -233,12 +233,12 @@ Date: 2016-09-18 ## 160912 -Date: 2016-09-11 +Date: September 11, 2016 ### Unity and CSharp upgrade warning -- The deprecation warnings described [below](#160822) have gone into effect. Deprecated APIs will now throw compiler errors when possible. -Likewise, the documentation for those APIs have been filtered from the main documentation. +- The deprecation warnings described in [160822](#160822) have gone into effect. Deprecated APIs will now throw compiler errors when possible. +Likewise, we filtered the documentation for those APIs from the main documentation. ### API changes @@ -249,11 +249,11 @@ Likewise, the documentation for those APIs have been filtered from the main docu ### LuaSDK specific changes - [LuaSDK](https://github.com/PlayFab/LuaSDK) - - Incremental Corona Support: There are new/interim zip-files which can be included in a Corona project. Proper Corona plugins are coming soon. + - Incremental Corona Support: There are new/interim zip-files that can be included in a Corona project. Proper Corona plugins are coming soon. ## 160829 -Date: 2016-08-28 +Date: August 28, 2016 ### API changes @@ -266,10 +266,10 @@ Date: 2016-08-28 - [Admin/GetPlayerTags](xref:titleid.playfabapi.com.admin.playstream.getplayertags) - [Admin/RemovePlayerTag](xref:titleid.playfabapi.com.admin.playstream.removeplayertag) -We have introduced segment tags, which provide a way of directly putting players into particular segments. You can now add one or more segment tags to each player. And then, when creating a segment, you can define the segment based on the segment tag. +We've introduced segment tags, which provide a way of directly putting players into particular segments. You can now add one or more segment tags to each player. And then, when creating a segment, you can define the segment based on the segment tag. -One intended use for Segment Tags is for integration with external analytics providers, like Appuri. The external analytics provider can perform its own advanced segmentation, such as "Likely to Churn", and then set a tag on players that match that segment. -All current deprecation changes have been released. Please see our blog post for details: +One intended use for Segment Tags is for integration with external analytics providers, like Appuri. The external analytics provider can perform its own advanced segmentation, such as "Likely to Churn," and then set a tag on players that match that segment. +Released all current deprecation changes. See our blog post for details: ### Cocos2d-xSDK specific changes @@ -280,19 +280,19 @@ All current deprecation changes have been released. Please see our blog post for ### PostmanCollection specific changes - [PostmanCollection](https://github.com/PlayFab/PostmanCollection) - - Added a header to all API methods which will help our servers track SDK usage. (This header already exists on all other SDKs). + - Added a header to all API methods, which help our servers track SDK usage. (This header already exists on all other SDKs). ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - We are pleased to announce the initial public beta release of our latest tool: Unity Editor Extensions. This plugin provides an easy-to-use interface for configuring and managing the PlayFab SDK. All Unity developers are encouraged to check out EdEx; There has never been an easier time to sign up and get started developing. - - Added an alternate implementation of `ExecuteCloudScript` which automatically parses `FunctionResult` into a target type, using a generic parameter. + - Unity Editor Extensions is now available as an initial public beta release. This plugin provides an easy-to-use interface for configuring and managing the PlayFab SDK. All Unity developers are encouraged to check out EdEx. Sign up and get started developing. + - Added an alternate implementation of `ExecuteCloudScript`, which automatically parses `FunctionResult` into a target type, using a generic parameter. - Failure cases in API methods are improved: Some cases that threw exceptions now properly report back to the error-callback (such as Web-Requests with no internet connection), and other cases report better information to the error-callback. -~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED: This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) -- ~~Fixed an issue where APIs containing an optional list field in the request would not post the request properly to the server. (Such as GetPlayerStatistics)~~ +- ~~Fixed an issue where APIs containing an optional list field in the request wouldn't post the request properly to the server. (Such as GetPlayerStatistics)~~ ### SDKGenerator specific changes @@ -301,14 +301,14 @@ All current deprecation changes have been released. Please see our blog post for ## 160822 -Date: 2016-08-21 +Date: August 21, 2016 ### Global upgrade warning Some SDKs have gained warnings for APIs that have become deprecated. -If you see these warnings, please resolve them ASAP, and migrate to the indicated replacement APIs. -Many of these APIs will be removed from the SDK within the next couple of months. -There is a blog post about this [here](https://blog.playfab.com/blog/deprecation-visibility/). +If you see these warnings, Resolve them ASAP, and migrate to the indicated replacement APIs. +Many of these APIs are removed from the SDK within the next couple of months. +There's a blog post about this [here](https://blog.playfab.com/blog/deprecation-visibility/). ### Deprecation notices @@ -388,16 +388,16 @@ There is a blog post about this [here](https://blog.playfab.com/blog/deprecation - **New PlayStream events** - - [player_tag_added](../api-references/events/player-tag-added.md) - - [player_tag_removed](../api-references/events/player-tag-removed.md) - - [title_catalog_updated](../api-references/events/title-catalog-updated.md) - - [title_store_updated](../api-references/events/title-store-updated.md) + - [player_tag_added](../api-references/events/PlayerIdentity/player-tag-added.md) + - [player_tag_removed](../api-references/events/PlayerIdentity/player-tag-removed.md) + - [title_catalog_updated](../api-references/events/CatalogV1/title-catalog-updated.md) + - [title_store_updated](../api-references/events/CatalogV1/title-store-updated.md) ### Global SDK changes - The example projects provided with the SDKs have all been updated, and no longer use deprecated APIs. - Several SDKs have compiler warnings and/or comments that describe deprecated elements of the API. -- The [PostmanCollection](https://github.com/PlayFab/PostmanCollection) internal format changed slightly. It will be less convenient to have multiple future versions of our [PostmanCollection](https://github.com/PlayFab/PostmanCollection) loaded at the same time (You'll get a warning about duplicate IDs). +- The [PostmanCollection](https://github.com/PlayFab/PostmanCollection) internal format changed slightly. It's less convenient to have multiple future versions of our [PostmanCollection](https://github.com/PlayFab/PostmanCollection) loaded at the same time (You get a warning about duplicate IDs). ### ActionScriptSDK specific changes @@ -406,12 +406,12 @@ There is a blog post about this [here](https://blog.playfab.com/blog/deprecation ## 160815 -Date: 2016-08-14 +Date: August 14, 2016 ### Unreal upgrade warning Required syntax changes for upgrading Unreal 4.12 -Best described by ZKShao in the pull request which helped resolve the problems: `` +Best described by ZKShao in the pull request that helped resolve the problems: `` ### API changes @@ -419,10 +419,10 @@ Best described by ZKShao in the pull request which helped resolve the problems: - **New PlayStream events:** - - [player_statistic_deleted](../api-references/events/player-statistic-deleted.md) - - [player_unlinked_account](../api-references/events/player-unlinked-account.md) + - [player_statistic_deleted](../api-references/events/Leaderboards/player-statistic-deleted.md) + - [player_unlinked_account](../api-references/events/PlayerIdentity/player-unlinked-account.md) -~~**UnrealCppSdk & UnrealBlueprintSdk specific changes:**~~ (UPDATED : These SDKs have been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealCppSdk & UnrealBlueprintSdk specific changes:**~~ (UPDATED: These SDKs are deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~Updated to support Unreal 4.12~~ - ~~Sadly, this requires dropping support for Unreal 4.11.x, due to conflicting requirements~~ @@ -435,7 +435,7 @@ Best described by ZKShao in the pull request which helped resolve the problems: - Game-servers can begin testing with registering callbacks to PlayStream events, and react in real-time - PlayFabSDK no longer requires permissions on Android. (WP8 and iOS still requires internet in build settings) - Phasing in deprecation warnings for APIs are out of date. - - These will later become deprecation errors, and will eventually be removed from the sdk. + - These will later become deprecation errors, and will eventually be removed from the SDK. - Some bug fixes for compression - PlayFabSdk now works in Unity 5.0 - Fixed specific devices on specific older unity versions, and expanded internal testing @@ -444,7 +444,7 @@ Best described by ZKShao in the pull request which helped resolve the problems: ## 160801 -Date: 2016-07-31 +Date: July 31, 2016 ### API changes @@ -467,59 +467,59 @@ Date: 2016-07-31 ## 160726 -Date: 2016-07-25 +Date: July 25, 2016 ### UnitySDK hotfix changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - Fixes for specific Devices on older Unity versions. - - Fix for specific `AdminApi` model classes which were being labeled as `PlayFabResultCommon` instead of `PlayFabRequestCommon`. + - Fix for specific `AdminApi` model classes that were being labeled as `PlayFabResultCommon` instead of `PlayFabRequestCommon`. - Known Issue: When using PlayFab UnitySdk, Google advertisingID and iOS IDFA no longer attribute correctly for Unity versions before 5.3. - The easiest fix is to upgrade your Unity3D version, but we will try to restore this in a later release of our SDK. ## 160725 -Date: 2016-07-24 +Date: July 24, 2016 ### API changes - **New PlayStream Event** - - [display_name_filtered](../api-references/events/display-name-filtered.md) (documentation available soon). + - [display_name_filtered](../api-references/events/Partner/display-name-filtered.md) (documentation available soon). - - Some API examples have been updated. + - Updated some API examples. - Lots of minor documentation updates. ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - Introduced a `PlayFabRequestCommon base-class`, which does compile-time type-checking for request objects passed to the API (This should not affect any users unless they're using non-standard request objects). + - Introduced a `PlayFabRequestCommon base-class`, which does compile-time type-checking for request objects passed to the API (This shouldn't affect any users unless they're using nonstandard request objects). - Fixed a null-reference bug in startup that some users have reported. - Fixed an issue with `ProductionEnvironmentUrl` in the `PlayFabSharedSettings` `ScriptableObject` that some users have reported. ## 160721 -Date: 2016-07-20 +Date: July 20, 2016 ### UnitySDK hotfix changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - Unity 4.7 works again, within the limitations of that version - - A bunch of small high-visibility fixes that have been noticed by many in the community have been fixed. - - UnitySDK V2 was promised to have full Windows Phone/Universal support (as well as other platforms like consoles). We're happy to say that all known issues have finally been fixed for all known platforms, and the PlayFab UnitySdk should work everywhere. + - Fixed a bunch of small high-visibility issues that many in the community noticed. + - UnitySDK V2 was promised to have full Windows Phone/Universal support (and other platforms like consoles). We're happy to say that all known issues have finally been fixed for all known platforms, and the PlayFab UnitySdk should work everywhere. - - Due to an unexpected side-effect in Unity, we won't be able to apply the `HideAndDontSave` flag to the PlayFab Http Object. [Details Here](https://answers.unity.com/questions/1218422/hideanddontsave-disables-ondestroy.html). - - We have added a set of extension functions to reflection, which make both standard C# and .NetCore C# do the same thing with the same lines of code, when possible. This extension it is not meant to be a complete solution for all possible reflection inconsistencies between those platforms. + - Due to an unexpected side-effect in Unity, we can't apply the `HideAndDontSave` flag to the PlayFab Http Object. [Details Here](https://answers.unity.com/questions/1218422/hideanddontsave-disables-ondestroy.html). + - We've added a set of extension functions to reflection, which make both standard C# and .NET Core C# do the same thing with the same lines of code, when possible. This extension isn't meant to be a complete solution for all possible reflection inconsistencies between those platforms. ## 160714 -Date: 2016-07-13 +Date: July 13, 2016 ### UnitySDK upgrade warning - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - We have released a new major revision for [UnitySDK](https://github.com/PlayFab/UnitySDK). (UPDATE : The UPGRADE Guide is obsolete). + - We've released a new major revision for [UnitySDK](https://github.com/PlayFab/UnitySDK). (UPDATE: The UPGRADE Guide is obsolete). ### API changes @@ -531,9 +531,9 @@ Date: 2016-07-13 - [UnlinkTwitch](xref:titleid.playfabapi.com.client.accountmanagement.unlinktwitch) - [GetPlayFabIDsFromTwitchIDs](xref:titleid.playfabapi.com.client.accountmanagement.getplayfabidsfromtwitchids) - **New PlayStream Events:** - - [title_exceeded_limit](../api-references/events/title-exceeded-limit.md) - - [title_limit_changed](../api-references/events/title-limit-changed.md) - - [title_requested_limit_change](../api-references/events/title-requested-limit-change.md) + - [title_exceeded_limit](../api-references/events/Extension/title-exceeded-limit.md) + - [title_limit_changed](../api-references/events/Extension/title-limit-changed.md) + - [title_requested_limit_change](../api-references/events/Title/title-requested-limit-change.md) ### LumberyardSDK specific changes @@ -542,45 +542,45 @@ Date: 2016-07-13 ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - A new major revision of [UnitySdk](https://github.com/PlayFab/UnitySDK) is going to be released very soon (hopefully today). - - The original UnitySdk will be available here for a limited time [UPDATE: Old link removed]. - - Version 2 of the [UnitySdk](https://github.com/PlayFab/UnitySDK) is currently available here: UnitySDKV2Beta [UPDATE: Old link removed], and will become the new [UnitySdk](https://github.com/PlayFab/UnitySDK) soon [UPDATE: Done]. + - A new major revision of [UnitySdk](https://github.com/PlayFab/UnitySDK) is going to be released soon (hopefully today). + - The original UnitySdk is available here for a limited time [UPDATE: Old link removed]. + - Version two of the [UnitySdk](https://github.com/PlayFab/UnitySDK) is currently available here: UnitySDKV2Beta [UPDATE: Old link removed], and becomes the new [UnitySdk](https://github.com/PlayFab/UnitySDK) soon [UPDATE: Done]. ## 160705 -Date: 2016-07-04 +Date: July 4, 2016 ### API changes - **New API** - [GetPlayerCombinedInfo](xref:titleid.playfabapi.com.client.accountmanagement.getplayercombinedinfo) - Lots of updated descriptions. - - All login calls have been updated to optionally return the [GetPlayerCombinedInfo](xref:titleid.playfabapi.com.client.accountmanagement.getplayercombinedinfo#getplayercombinedinforesultpayload) results. - - `GetUserCombinedInfo` API will be deprecated in favor of [GetPlayerCombinedInfo](xref:titleid.playfabapi.com.client.accountmanagement.getplayercombinedinfo) in the near future. + - Updated all login calls to optionally return the [GetPlayerCombinedInfo](xref:titleid.playfabapi.com.client.accountmanagement.getplayercombinedinfo#getplayercombinedinforesultpayload) results. + - `GetUserCombinedInfo` API is deprecated in favor of [GetPlayerCombinedInfo](xref:titleid.playfabapi.com.client.accountmanagement.getplayercombinedinfo) soon. ### UnitySDK specific changes -- GZip compression mode has been restored for api-requests done with `PlayFabSettings.RequestType = WebRequestType.UnityWww`; +- Restored GZip compression mode for api-requests done with `PlayFabSettings.RequestType = WebRequestType.UnityWww`; -- A `JsonProperty` attribute has been added to `SimpleJson` and supports alternate naming of fields/properties, and omitting nulls from the serialized json. -- TimeSpans serialized with the default PlayFab `SimpleJson` strategy will now serialize as a float number of seconds. Formerly, they would serialize as structs which wasn't supported by the API or any cross-platform options. -- Support for certain platforms (EG: consoles, iOS) that build using Mono2x mode will not be supported until goes live. -- Support for Windows Universal will not be supported until goes live. -- See this blog post for more details: +- Added a `JsonProperty` attribute to `SimpleJson` that supports alternate naming of fields/properties, and omitting nulls from the serialized json. +- TimeSpans serialize with the default PlayFab `SimpleJson` strategy as a float number of seconds. Formerly, they serialize as structs, which aren't supported by the API or any cross-platform options. +- Support for certain platforms (EG: consoles, iOS) that build using Mono2x mode isn't supported until goes live. +- Support for Windows Universal isn't supported until goes live. +- For more information, see this blog post: (standalone and android work correctly and are supported for all options) -- All platforms that can utilize IL2CPP are supported in that mode. -- This version was initially launched with an issue where compression did not always work. It was hot-fixed on July-8. Initial downloads before this date may have compression issues, which can be solved by updating, or by disabling compression: (PlayFabSettings.CompressApiData = false;) +- All platforms that can use IL2CPP are supported in that mode. +- This version was initially launched with an issue where compression doesn't work consistently. It was hot-fixed on July-8. Initial downloads before this date may have compression issues, which can be solved by updating, or by disabling compression: (PlayFabSettings.CompressApiData = false;) ## 160627 -Date: 2016-06-26 +Date: June 26, 2016 ### UnitySDK upgrade warning - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - `PlayFab.Internal.Util` has been renamed to `PlayFab.Internal.PlayFabUtil`. The "Util" name is very common and exists in the root level for many projects, which causes name conflicts for those customers. + - Renamed `PlayFab.Internal.Util` to `PlayFab.Internal.PlayFabUtil`. The "Util" name is common and exists in the root level for many projects, which causes name conflicts for those customers. - - When updating PlayFab-UnitySdk, you may see some deprecation warnings if you are using PlayFab's implementation of SimpleJson. Please resolve these at your leisure. + - When updating PlayFab-UnitySdk, you may see some deprecation warnings if you're using PlayFab's implementation of SimpleJson. Resolve these at your leisure. ### API changes @@ -591,28 +591,28 @@ Date: 2016-06-26 - **New PlayStream events** - - [character_consumed_item](../api-references/events/character-consumed-item.md) - - [character_created](../api-references/events/character-created.md) - - [character_inventory_item_added](../api-references/events/character-inventory-item-added.md) - - [character_statistic_changed](../api-references/events/character-statistic-changed.md) - - [character_vc_item_purchased](../api-references/events/character-vc-item-purchased.md) - - [character_virtual_currency_balance_changed](../api-references/events/character-virtual-currency-balance-changed.md) - - [player_redeemed_coupon](../api-references/events/player-redeemed-coupon.md) + - [character_consumed_item](../api-references/events/Character/character-consumed-item.md) + - [character_created](../api-references/events/PlayerIdentity/character-created.md) + - [character_inventory_item_added](../api-references/events/Character/character-inventory-item-added.md) + - [character_statistic_changed](../api-references/events/Leaderboards/character-statistic-changed.md) + - [character_vc_item_purchased](../api-references/events/Character/character-vc-item-purchased.md) + - [character_virtual_currency_balance_changed](../api-references/events/Character/character-virtual-currency-balance-changed.md) + - [player_redeemed_coupon](../api-references/events/Player/player-redeemed-coupon.md) ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - Known issues: Windows Store apps, and non-IL2CPP build options do not work yet. Stay tuned for a blog post about these issues and our new repository: UnitySDKV2Beta [UPDATE: Old link removed]. + - Known issues: Windows Store apps, and non-IL2CPP build options don't work yet. Stay tuned for a blog post about these issues and our new repository: UnitySDKV2Beta [UPDATE: Old link removed]. - We discovered a name-conflict with the core `UnityEngine` DLL, specifically an empty namespace called ``SimpleJson``. As such, we've had to rename and reorganize our JSON classes... again. Many apologies. ## 160613 -Date: 2016-06-12 +Date: June 12, 2016 ### Global SDK upgrade warning -- PlayFabSettings and PlayFabVersion: These files and their contents have been merged into PlayFabSettings. -- If you were previously referencing the PlayFabVersion variables, update to the same/very-similar variable in PlayFabSettings. +- PlayFabSettings and PlayFabVersion: Merged these files and their contents into PlayFabSettings. +- If you were previously referencing the PlayFabVersion variables, update to the similar variable in PlayFabSettings. ### API changes @@ -625,30 +625,30 @@ Date: 2016-06-12 ### SDK global changes -- Please note that `RunCloudScript` has been deprecated since March 2016, and will be removed from the sdks in the near future. Please convert to [ExecuteCloudScript](xref:titleid.playfabapi.com.client.server-sidecloudscript.executecloudscript) asap. +- We deprecated `RunCloudScript` since March 2016, and it's removed from the SDKs soon. Convert to [ExecuteCloudScript](xref:titleid.playfabapi.com.client.server-sidecloudscript.executecloudscript) as soon as possible. -- Please stay tuned for a blog post about an internal testing system we call Jenkernaught. Our example projects contain some changes oriented towards deeper testing to improve sdk stability and reliability. Some specifics: -- All testing and examples for CloudScript have been updated to [ExecuteCloudScript](xref:titleid.playfabapi.com.client.server-sidecloudscript.executecloudscript), since RunCloudScript is deprecated. -- All testing and examples for successful login have been updated to `LoginWithCustomID`, to make internal testing easier. +- Stay tuned for a blog post about an internal testing system we call Jenkernaught. Our example projects contain some changes oriented towards deeper testing to improve SDK stability and reliability. Some specifics: +- Updated all testing and examples for CloudScript to [ExecuteCloudScript](xref:titleid.playfabapi.com.client.server-sidecloudscript.executecloudscript), since RunCloudScript is deprecated. +- Updated all testing and examples for successful login to `LoginWithCustomID`, to make internal testing easier. ### Cocos2d-xSDK specific changes - [Cocos2d-xSDK](https://github.com/PlayFab/Cocos2d-xSDK) - - `MultitypeVar` can contain a `PlayFabBaseModel` for the purposes of writing request objects. It still cannot receive an arbitrary json object for results. + - `MultitypeVar` can contain a `PlayFabBaseModel` for the purposes of writing request objects. It still can't receive an arbitrary json object for results. - Initial versioned release. -~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED: This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) -- ~~Removed version info from a bunch of header-comments to avoid spammy check ins (So, this is the last spammy check in)~~ +- ~~Removed version info from a bunch of header-comments to avoid spammy check-ins (So, this is the last spammy check in)~~ - ~~A missing http header is now provided.~~ ## 160606 -Date: 2016-06-05 +Date: June 5, 2016 ### Global SDK upgrade warning -For consistency across all sdks, the `sdkRevision` variable was renamed to `sdkVersion` ([ActionScriptSDK](https://github.com/PlayFab/ActionScriptSDK), [JavaSDK](https://github.com/PlayFab/JavaSDK), [UnitySdk](https://github.com/PlayFab/UnitySDK)). +For consistency across all SDKs, we renamed the `sdkRevision` variable to `sdkVersion` ([ActionScriptSDK](https://github.com/PlayFab/ActionScriptSDK), [JavaSDK](https://github.com/PlayFab/JavaSDK), [UnitySdk](https://github.com/PlayFab/UnitySDK)). If you were accessing `sdkRevision`, switch to `sdkVersion`. ### API changes @@ -659,8 +659,8 @@ If you were accessing `sdkRevision`, switch to `sdkVersion`. - More steps towards the deprecation of `RunCloudScript`, so customers should plan to migrate to [ExecuteCloudScript](xref:titleid.playfabapi.com.client.server-sidecloudscript.executecloudscript) for live projects. -- Internally, we are halfway through a push to improve testing multi-platform testing for all sdks. [SDKGenerator](https://github.com/PlayFab/SDKGenerator) users may find references to `Jenkernaught` and `buildIdentifier`. `Jenkernaught` is the code-name for the tech that enables this improved platform testing. `buildIdentifier` is a new variable in all sdks indicating the specific PlayFab-Jenkins job which generated a particular sdk version. -- There will be blog-post describing what the `Jenkernaught` does, and more detailed test-framework changes omitted from here, so stay tuned. +- Internally, we're halfway through a push to improve testing multi-platform testing for all SDKs. [SDKGenerator](https://github.com/PlayFab/SDKGenerator) users may find references to `Jenkernaught` and `buildIdentifier`. `Jenkernaught` is the code-name for the tech that enables this improved platform testing. `buildIdentifier` is a new variable in all SDKs indicating the specific PlayFab-Jenkins job which generated a particular SDK version. +- There's a blog post describing what the `Jenkernaught` does, and more detailed test-framework changes omitted from here, so stay tuned. ### ActionScriptSDK specific changes @@ -677,75 +677,75 @@ If you were accessing `sdkRevision`, switch to `sdkVersion`. ### JavaScriptSDK specific changes - [JavaScriptSDK](https://github.com/PlayFab/JavaScriptSDK) - - Added a utility function to the `PlayFabClientSDK: IsClientLoggedIn()`. Please use this to determine this condition. + - Added a utility function to the `PlayFabClientSDK: IsClientLoggedIn()`. Use this to determine this condition. - Minor `Jenkernaught` related test-changes example/testing project. ### NodeSDK specific changes - [NodeSDK](https://github.com/PlayFab/NodeSDK) - - Added a utility function to the `PlayFabClientSDK: IsClientLoggedIn()`. Please use this to determine this condition. + - Added a utility function to the `PlayFabClientSDK: IsClientLoggedIn()`. Use this to determine this condition. - Minor `Jenkernaught` related test-changes example/testing project. ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - Fixed a critical bug where PlayFab API calls would stop working if you changed scenes. + - Fixed a critical bug where PlayFab API calls stop working if you change scenes. - Adjusted the defaults for timestamp formats to be consistent with other PlayFab SDKs. - - We are still having issues with Windows-Phone and Windows-Universal for Unity versions 5.3 or higher, which we hope to fix soon. + - We're still having issues with Windows-Phone and Windows-Universal for Unity versions 5.3 or higher, which we hope to fix soon. ## 160523 -Date: 2016-05-22 +Date: May 22, 2016 ### Global SDK upgrade warning -Various APIs that save versioned data (UserData, CharacterData, and others) have had a datatype change from int to uint. This will require some users to remove/alter some casting where our api was formerly inconsistent. Some developers may need to change some local variables from int to uint. +Various APIs that save versioned data (UserData, CharacterData, and others) had a datatype change from int to uint. This requires some users to remove/alter some casting where our api was formerly inconsistent. Some developers may need to change some local variables from int to uint. -~~**UnrealBlueprintSdk upgrade warning:**~~ ~~There was a naming conflict between xcode and some of the playfab enums. As a result, we've had to revise the blueprint-enums again, which breaks all PlayFab-api-nodes using enums. The upgrade process in-editor is to delete and re-create each affected blueprint node (they will throw in-editor-compiler warnings if they're affected).~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealBlueprintSdk upgrade warning:**~~ ~~There was a naming conflict between xcode and some of the playfab enums. As a result, we've had to revise the blueprint-enums again, which breaks all PlayFab-api-nodes using enums. The upgrade process in-editor is to delete and re-create each affected blueprint node (they will throw in-editor-compiler warnings if they're affected).~~ (UPDATED: This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) ### API changes -- There were some `DataVersion` vars which were set to an inconsistent datatype (int and uint in various APIs). All of these have been changed to uint for consistency. +- Some `DataVersion` vars used an inconsistent datatype (int and uint in various APIs). We changed all of these to uint for consistency. -- Some additional options have been added to APIs related to Matchmaking. -- The matchmaker now takes an additional parameter (`StartNewIfNoneFound`), which allows titles to determine whether a new server should spin up if no results are found in the matchmaking process. By default, `StartNewIfNoneFound` is `true`, meaning that a new session will be created if one cannot be found which matches the requirements. This allows titles with skill-based matchmaking to potentially "loosen" the requirements for a match, to get players with skill levels at the far ends of the bell curve into games more quickly. +- Added more options to APIs related to Matchmaking. +- The matchmaker now takes an extra parameter (`StartNewIfNoneFound`), which allows titles to determine whether a new server should spin up if no results are found in the matchmaking process. By default, `StartNewIfNoneFound` is `true`, meaning that a new session is created if one can't be found that matches the requirements. This allows titles with skill-based matchmaking to potentially "loosen" the requirements for a match, to get players with skill levels at the far ends of the bell curve into games more quickly. -- Updated the custom game server logic with `GameInstanceState`, which determines whether the game session is available for matchmaking. Games which are `Closed` are not available for matchmaking, allowing developers to create game sessions which are specific to a group of players, as well as to prevent post-start joins of a game session in progress. By default, game servers start in an Open state. +- Updated the custom game server logic with `GameInstanceState`, which determines whether the game session is available for matchmaking. Games which are `Closed` aren't available for matchmaking, allowing developers to create game sessions which are specific to a group of players, and to prevent post-start joins of a game session in progress. By default, game servers start in an Open state. - - -~~New API: `SetGameServerInstanceState` call can be used by the server to set its state, and `StartOpen` has been added to the `GameModeInfo` used in calls to `ModifyMatchmakerGameModes`, to allow specifying whether sessions in a game mode start as `Open` (the default) or `Closed`.~~(UPDATED: This is deprecated. See [Servers](../multiplayer/servers/index.md)) + -~~New API: `SetGameServerInstanceState` call can be used by the server to set its state, and `StartOpen` is added to the `GameModeInfo` used in calls to `ModifyMatchmakerGameModes`, to allow specifying whether sessions in a game mode start as `Open` (the default) or `Closed`.~~(UPDATED: This is deprecated. See [Servers](../multiplayer/servers/index.md)) -~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED: This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~Internal SDK updates that make it easier to execute and handle API calls from C++.~~ -- ~~Added an internal testing suite which allows thorough verification of PlayFab functionality on all target devices. (Example project only, not the core plugin)~~ +- ~~Added an internal testing suite that allows thorough verification of PlayFab functionality on all target devices. (Example project only, not the core plugin)~~ - ~~A bunch of C++ code cleanup, and improvements on logging and warnings.~~ - ~~Resolved a concurrency problem with multiple synchronous api calls for Blueprints and C++ calls.~~ ## 160502 -Date: 2016-05-01 +Date: May 1, 2016 ### Global SDK upgrade warning -If you were previously setting the `ConfirmationMessage` and `ForceLink` fields, simply remove them. +If you were previously setting the `ConfirmationMessage` and `ForceLink` fields, remove them. ### API changes - New Admin API: - - ~~**SetStoreSegmentOverrides**~~ (UPDATE : This API has been removed) + - ~~**SetStoreSegmentOverrides**~~ (UPDATE: This API is removed) - Some deprecated and internal fields are no longer published with the SDK: ConfirmationMessage and ForceLink. -~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED: This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~Revised the readme and the example project to use a simpler login process, and the new simpler ExecuteCloudScript method.~~ -- ~~When there is an api error, the details of that error will report more accurately and display better debug information.~~ -- ~~We are removing the "Beta" flagging from Unreal sdks, they are now a full member of our SDK collection, with full support and quality checks.~~ +- ~~When there's an API error, the details of that error report more accurately and display better debug information.~~ +- ~~We're removing the "Beta" flagging from Unreal SDKs, they're now a full member of our SDK collection, with full support and quality checks.~~ ## 160425 -Date: 2016-04-24 +Date: April 24, 2016 -~~**UnrealBlueprintSdk Upgrade warning:** Many blueprint-api-calls which have enum fields will have to be updated to utilize the enum dropdown. The old value will be lost, and must be re-set. This affects dozens of PlayFab blueprint nodes.~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealBlueprintSdk Upgrade warning:** Many blueprint-api-calls which have enum fields will have to be updated to utilize the enum dropdown. The old value will be lost, and must be reset. This affects dozens of PlayFab blueprint nodes.~~ (UPDATED: This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) ### API changes @@ -757,19 +757,19 @@ Date: 2016-04-24 ### Cocos2d-xSDK specific changes - [Cocos2d-xSDK](https://github.com/PlayFab/Cocos2d-xSDK) - - Cocos SDK has been overhauled. - - New testing framework, internal Http functionality has been converted. + - Overhauled the Cocos SDK. + - New testing framework, converted internal Http functionality. - Android, iOS, and Win32 platforms are all working. - Lots of other small fixes and improvements. -~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED: This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~UnrealBlueprintSdk is nearing the end of its limited-support Beta period. As such, there will be some potentially breaking changes in the next few releases.~~ -- ~~There are data fields in the Api-specification defined as enums. Formerly, UnrealBlueprintSdk displayed these fields as arbitrary strings, and the user was expected to input the correct option. This has been fixed. All these fields have been converted to be enum-dropdowns in the blueprints.~~ +- ~~There are data fields in the Api-specification defined as enums. Formerly, UnrealBlueprintSdk displayed these fields as arbitrary strings, and the user was expected to input the correct option. This is fixed. All these fields are converted to be enum-dropdowns in the blueprints.~~ ## 160414 -Date: 2016-04-13 +Date: April 13, 2016 ### API changes @@ -780,11 +780,11 @@ Date: 2016-04-13 - [UnitySDK](https://github.com/PlayFab/UnitySDK) - More automated testing to improve stability of SDKs (and some associated bug fixes) - - Specifically, a new PlayStream test and making tests more consistent across all sdks. + - Specifically, a new PlayStream test and making tests more consistent across all SDKs. ## 160328 -Date: 2016-03-27 +Date: March 27, 2016 ### API changes @@ -792,7 +792,7 @@ Date: 2016-03-27 - Minor revisions in the way that CloudScript is uploaded via Admin-API. - Continuing to revise and define API limits and overage definitions where needed. -- "PlayFabId" input has been removed from the documentation on a few client APIs, which never used that value. +- Removed "PlayFabId" input from the documentation on a few client APIs, which never used that value. - Lots of minor documentation updates. - New `ExecuteCloudScript` API, which replaces the older pattern of `GetCloudScriptUrl+RunCloudScript`. - This should make it easier for novice users to call CloudScript correctly. @@ -801,21 +801,21 @@ Date: 2016-03-27 - [Cocos2d-xSDK](https://github.com/PlayFab/Cocos2d-xSDK) - Project folder structure updated to be consistent across all platforms. - - This fixes the issue where iOS build would fail to import some code files. + - This fixes the issue where iOS build fails to import some code files. - Cocos is now tested and working for Win32 and iOS. ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - Fixing inconsistent `#define` options which led to errors with `ReadAllText` function. - - Known Issue (not resolved): `SimpleJson` does not serialize correctly when using the Player Setting Scripting Back end option: `Mono2x`. Until this is fixed, please use `IL2CPP` if possible. + - Fixing inconsistent `#define` options that led to errors with `ReadAllText` function. + - Known Issue (not resolved): `SimpleJson` doesn't serialize correctly when using the Player Setting Scripting Back end option: `Mono2x`. Until this is fixed, use `IL2CPP` if possible. - (A similar issue may be present when building for PlayStation®.) "PlayStation" is a registered trademark or trademark of Sony Interactive Entertainment Inc. ## 160307 -Date: 2016-03-06 +Date: March 6, 2016 ### API changes @@ -840,7 +840,7 @@ Date: 2016-03-06 ## 160222 -Date: 2016-02-21 +Date: February 21, 2016 ### API changes @@ -860,23 +860,23 @@ Date: 2016-02-21 - [UnitySDK](https://github.com/PlayFab/UnitySDK) - Updated Helper Function Signatures in the testing harness. - - Added structural changes to switch our internal JSON serializer from JSON.net to SimpleJson (This is an effort to enable Universal Windows Builds). + - Added structural changes to switch our internal JSON serializer from JSON.NET to SimpleJson (This is an effort to enable Universal Windows Builds). ## 160215 -Date: 2016-02-14 +Date: February 14, 2016 ### API changes - Resettable Leaderboards and Player Statistics are now live. -- `GetPlayFabIDsFromSteamIDs` accepts and returns string IDs for languages that cannot handle ulong values. +- `GetPlayFabIDsFromSteamIDs` accepts and returns string IDs for languages that can't handle ulong values. - Minor changes to support Parse migrations. - Minor documentation adjustments. ## 160208 -Date: 2016-02-07 +Date: February 7, 2016 ### API changes @@ -887,16 +887,16 @@ Date: 2016-02-07 - `server.UnlockContainerItem` - `server.UnlockContainerItem` - `server.UnlockContainerInstance` -- Added `admin.StatisticResetIntervalOption` for use in resetable leaderboards. +- Added `admin.StatisticResetIntervalOption` for use in resettable leaderboards. ### UnitySdk specific changes - [UnitySdk](https://github.com/PlayFab/UnitySDK) - - Modified the project folder structure a bit, which may cause some file conflicts. Please see this [forum post](https://community.playfab.com/questions/321/206711137-Best-way-to-update-the-PlayFab-Unity-SDK-.html) for details. + - Modified the project folder structure a bit, which may cause some file conflicts. See this [forum post](https://community.playfab.com/questions/321/206711137-Best-way-to-update-the-PlayFab-Unity-SDK-.html) for details. ## 160201 -Date: 2016-01-31 +Date: January 31, 2016 ### API changes @@ -912,7 +912,7 @@ Date: 2016-01-31 ## 160125 -Date: 2016-01-24 +Date: January 24, 2016 ### API changes @@ -922,22 +922,22 @@ Date: 2016-01-24 - `Client.UpdateCharacterStatistics` - `Server.RevokeInventoryItem` - Fixed typo in `PurchaseItem___` -> `PurchaseItem___`. - - Updated `UserAccountInfo` to contain additional account details. + - Updated `UserAccountInfo` to contain more account details. -~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealBlueprintSdk specific changes:**~~ (UPDATED: This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~Fixed a Client issue that prevented subsequent calls after login from working.~~ ## 160118 -Date: 2016-01-17 +Date: January 17, 2016 ### API changes -- New leaderboard apis are available: +- New leaderboard APIs are available: - `GetLeaderboardAroundPlayer` - `GetFriendLeaderboardAroundPlayer` -- Old leaderboard apis are deprecated: +- Old leaderboard APIs are deprecated: - `GetFriendLeaderboardAroundCurrentUser` - `GetLeaderboardAroundCurrentUser` - Lots of minor documentation improvements. @@ -956,7 +956,7 @@ Date: 2016-01-17 - [UnitySDK](https://github.com/PlayFab/UnitySDK) - Deleted some internal testing systems (DemoScene folder) from the public SDK. - - We are prototyping new samples and event systems. Some of the underlying SDK changes are visible in the diff, but none of it is accessible yet. Stay tuned as it's almost done. + - We're prototyping new samples and event systems. Some of the underlying SDK changes are visible in the diff, but none of it's accessible yet. Stay tuned as it's almost done. - An alternate version of the unit-tests are available on the client, with client-only api calls. ### Cocos2d-xSDK & WindowsSDK/C++ specific changes diff --git a/playfab-docs/release-notes/2017.md b/playfab-docs/release-notes/2017.md index bb4132efa..91c496b8d 100644 --- a/playfab-docs/release-notes/2017.md +++ b/playfab-docs/release-notes/2017.md @@ -6,7 +6,7 @@ ms.author: jenelleb ms.date: 07/12/2018 ms.topic: article ms.service: azure-playfab -keywords: playfab, development, release, apis, features +keywords: playfab, development, release, APIs, features ms.localizationpriority: medium --- @@ -14,23 +14,23 @@ ms.localizationpriority: medium ## 171204 -Date: 2017-12-04 +Date: December 4, 2017 ### Unreal SDK changes (Cpp and Bp) - Updated both SDKs to **Unreal 4.18.1**. -- Older versions will still work, but require un-commenting `#defines` in the \_.build.cs files. +- Older versions still work, but require uncommenting `#defines` in the \_.build.cs files. ## 171127 -Date: 2017-11-27 +Date: November 27, 2017 ### API changes - An inventory feature allowing "Limited Edition" items is now released from beta. -- This lets you define that only a fixed number of a particular `itemId` will be available in your game. -- A virtual currency property has been removed from API methods that use "[ProfileModel](xref:titleid.playfabapi.com.client.accountmanagement.getplayerprofile#playerprofilemodel)", as that information was never actually provided or correct. It will return... someday. +- This feature lets you define that only a fixed number of a particular `itemId` is available in your game. +- Removed a virtual currency property from API methods that use "[ProfileModel](xref:titleid.playfabapi.com.client.accountmanagement.getplayerprofile#playerprofilemodel)", as that information is never provided or correct. It returns... someday. ### New API methods @@ -39,7 +39,7 @@ Date: 2017-11-27 - client.[GetPaymentToken](xref:titleid.playfabapi.com.client.playeritemmanagement.getpaymenttoken) - Used for [XSolla specific payment processing](../economy-monetization/economy/tutorials/non-receipt-payment-processing.md) - client.[ReportDeviceInfo](xref:titleid.playfabapi.com.client.analytics.reportdeviceinfo) - - This API method is not meant to be called directly. It is currently a built-in feature for Unity and Lumberyard SDKs. It can be disabled with the [API Policy](../api-references/api-access-policy.md). Additionally, we will be adding another option soon to disable in the title settings page in Game Manager. + - This API method isn't meant to be called directly. It's currently a built-in feature for Unity and Lumberyard SDKs. It can be disabled with the [API Policy](../api-references/api-access-policy.md). Additionally, we're adding another option soon to disable in the title settings page in Game Manager. ### Updated API method error codes @@ -51,20 +51,20 @@ Date: 2017-11-27 ### SDK specific updates -- [UnitySdk](https://github.com/PlayFab/UnitySDK): We are now building all published unity package files with Unity 2017.2.0f3. +- [UnitySdk](https://github.com/PlayFab/UnitySDK): We're now building all published unity package files with Unity 2017.2.0f3. - For testing, we internally updated to the latest for each major.minor version, from Unity 4.7.2f1 to 2017.1.2f1. - Unity Example Test Game Server: Fix applied to `HttpHelper` to fix SSL validation on `SignalR` requests. - [ActionScriptSDK](https://github.com/PlayFab/ActionScriptSDK): AirSdk in example updated to v27. -- [Cocos2d-xSDK](https://github.com/PlayFab/Cocos2d-xSDK): We are still targeting 3.15.1, despite 3.16 Cocos release (stay tuned). +- [Cocos2d-xSDK](https://github.com/PlayFab/Cocos2d-xSDK): We're still targeting 3.15.1, despite the 3.16 Cocos release (stay tuned). - SdkTestingCloudScript and [NodeSDK](https://github.com/PlayFab/NodeSDK): Updated the example VS projects to support VS/msbuild 2017. -- WindowsSDK: This will be the last build of the nuget package targeting Visual Studio 2013: - - [WindowsSdk VS 2013 Nuget Package](https://www.nuget.org/packages/com.playfab.windowssdk.v120/1.19.171127) - - We are updating our automated build machines, and we won't be installing VS 2013 on the new ones. - - The [newer nuget package](https://www.nuget.org/packages/com.playfab.windowssdk.v140/) will continue to work on VS 2015 and 2017. +- WindowsSDK: This is the last build of the NuGet package targeting Visual Studio 2013: + - [WindowsSdk VS 2013 NuGet Package](https://www.NuGet.org/packages/com.playfab.windowssdk.v120/1.19.171127) + - We're updating our automated build machines, and we aren't installing VS 2013 on the new ones. + - The [newer NuGet package](https://www.NuGet.org/packages/com.playfab.windowssdk.v140/) will continue to work on VS 2015 and 2017. ## 171106 -Date: 2017-11-06 +Date: November 6, 2017 ### New API methods @@ -73,16 +73,16 @@ Date: 2017-11-06 ### Updated PlayStream event -- [sent_email](../api-references/events/sent-email.md) gains new fields: Body, and Subject. +- [sent_email](../api-references/events/TitleCommunications/sent-email.md) gains new fields: Body, and Subject. ### All SDKs - **MINOR SDK BREAKING CHANGE:** `ForgetClientCredentials()` renamed to `ForgetAllCredentials()`. -- This is part of a "coming soon" feature, which will be announced when complete. +- This is part of a "coming soon" feature, which is announced when complete. ## 171102 -Date: 2017-11-02 +Date: November 2, 2017 ### New PlayFab feature @@ -103,36 +103,36 @@ Date: 2017-11-02 ### New PlayStream events -- [auth_token_validated](../api-references/events/auth-token-validated.md) -- [player_updated_contact_email](../api-references/events/player-updated-contact-email.md) -- [sent_email](../api-references/events/sent-email.md) +- [auth_token_validated](../api-references/events/PlayerIdentity/auth-token-validated.md) +- [player_updated_contact_email](../api-references/events/PlayerIdentity/player-updated-contact-email.md) +- [sent_email](../api-references/events/TitleCommunications/sent-email.md) ### Unreal specific update -- Our auto builder failed to publish the Unreal SDKs for build number 171016 and 171026. The issue with our auto-builder has been resolved, and version 171026 has been published after the fact, and releases will resume normally +- Our auto builder failed to publish the Unreal SDKs for build number 171016 and 171026. We resolved the issue with our auto-builder, published version 171026 after the fact, and releases resumed normally ### Unity specific changes -- **MINOR BREAKING CHANGE:** `ForgetClientCredentials` has been renamed to `ForgetAllCredentials`. -- This is part of a new feature that will be coming soon. `ForgetClientCredentials` will be renamed to `ForgetAllCredentials` in all SDKs over the next few releases. +- **MINOR BREAKING CHANGE:** Renamed `ForgetClientCredentials` to `ForgetAllCredentials`. +- This is part of a new feature coming soon. We're renaming `ForgetClientCredentials` to `ForgetAllCredentials` in all SDKs over the next few releases. ## 171026 -Date: 2017-10-26 +Date: October 26, 2017 ### API documentation changes - Updating error codes for API methods. -- Many error codes that are universal to all API methods have been removed from the per-API-method list. A new page will be made which describes universal error codes. +- Removed many error codes that are universal to all API methods from the per-API-method list. A new page describes universal error codes. - **Removed Universal Codes:** - InvalidParams - OverLimit - DataUpdateRateExceeded - AccountBanned - These errors (and others, to be published in a separate document), can be returned from any API method and should be handled appropriately. -- New error codes have been added to several dozen API methods, and a few false codes removed. The error code lists should be much more accurate for method-specific error returns. This is still an ongoing process, so there will be more updates. -- Several API methods involving virtual currency can decrease the balance below zero. These have been labeled appropriately. +- Added new error codes to several dozen API methods, and removed a few false codes. The error code lists should be much more accurate for method-specific error returns. This is still an ongoing process, so there are more updates. +- Several API methods involving virtual currency can decrease the balance to less than zero. We labeled these appropriately. ### API changes @@ -144,12 +144,12 @@ Date: 2017-10-26 ### Game Manager changes -- You can now delete titles using the new Admin/DeleteTitle API, or on the Game Manager studios page, as shown below. +- You can now delete titles using the new Admin/DeleteTitle API, or on the Game Manager studios page, as shown in the following image. ![DelTitleGameManager](images/171026-DelTitleGameManager.png) ## 171016 -Date: 2017-10-16 +Date: October 16, 2017 ### API changes @@ -158,8 +158,8 @@ Date: 2017-10-16 ### New PlayStream events -- [player_started_purchase](../api-references/events/player-started-purchase.md) -- [player_paid_for_purchase](../api-references/events/player-paid-for-purchase.md) +- [player_started_purchase](../api-references/events/Player/player-started-purchase.md) +- [player_paid_for_purchase](../api-references/events/Player/player-paid-for-purchase.md) ### JavaScriptSDK specific changes @@ -169,16 +169,16 @@ Date: 2017-10-16 ### LuaSDK specific changes - [LuaSDK](https://github.com/PlayFab/LuaSDK) - - Our Lua publish pipeline has been fixed, and LuaSDK is being updated properly again. + - Fixed our Lua publish pipeline, and LuaSDK is being updated properly again. ### UnitySdk specific changes - [UnitySdk](https://github.com/PlayFab/UnitySDK) - - A [regression in Unity](https://issuetracker.unity3d.com/issues/unitywebrequest-getresponseheaders-method-returns-null-on-android-devices) has been handled on our side, and should no longer affect PlayFab customers. + - We handled a [regression in Unity](https://issuetracker.unity3d.com/issues/unitywebrequest-getresponseheaders-method-returns-null-on-android-devices) on our side, and it should no longer affect PlayFab customers. -~~**UnrealCppSdk specific changes:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealCppSdk specific changes:**~~ (UPDATED : This SDK is deprecated. For the new unreal SDK, refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) -- ~~One of our customers has made an add-on plugin to our SDK which integrates the Unreal OnlineSubsystem & the PlayFab SDK~~ +- ~~One of our customers has made an add-on plugin to our SDK, which integrates the Unreal OnlineSubsystem & the PlayFab SDK~~ - ~~You can check it out [here](https://gitlab.com/mtuska/OnlineSubsystemPlayFab).~~ ### Unicorn Battle example @@ -187,30 +187,30 @@ Date: 2017-10-16 ## 170925 -Date: 2017-09-05 +Date: September 5, 2017 ### API Changes -- A handful of beta APIs that were never made public have been removed. This should not affect any current customers or live titles. +- Removed a handful of beta APIs that were never made public. This shouldn't affect any current customers or live titles. - We bypassed the default language-level header checks in our CloudScript engine. This means several CloudScript http.request() headers that were formerly being rejected should now work. ### Global Push Notification update -- Please see [our blog](https://blog.playfab.com/blog/push-sep-17) for details about the improvements to Push Notifications +- See [our blog](https://blog.playfab.com/blog/push-sep-17) for details about the improvements to Push Notifications ### New PlayStream events -- [player_device_info](../api-references/events/player-device-info.md) +- [player_device_info](../api-references/events/PlayerIdentity/player-device-info.md) - Games using the latest UnitySDK can now see some basic analytics data about their customers. SnowFlake is ideal for viewing and analyzing this information, but it's also available in the PlayStream Event History. - player_updated_membership ### JavaScriptSDK specific changes - [JavaScriptSDK](https://github.com/PlayFab/JavaScriptSDK) - - A handful of mini-features that exist in other SDKs have been added to JavaScriptSDK: + - Added a handful of mini-features that exist in other SDKs to JavaScriptSDK: - You can now inject extra headers into requests (removing one of the blockers for Double Encrypted Logins with this SDK). - Added a new function: `PlayFabClientSDK.ForgetClientCredentials()` - - This is a convenience function that allows you to reset the client after shutting down or logging out. + - This is a convenience function that resets the client after shutting down or logging out. - `PlayFab.GenerateErrorReport()` - This is a convenience function that converts the error-result from a failed PlayFab call into a single complete description of how the call failed. - Added optional data relays into the PlayFab API requests: @@ -222,40 +222,40 @@ Date: 2017-09-05 ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - New experimental feature: This release of PlayFab UnitySDK now optionally allows you to see device information for your players. Example information you can see is: memory, resolution, user-agent, device-type, OS version, etc. + - New experimental feature: This release of PlayFab UnitySDK now optionally lets you see device information for your players. Example information you can see is: memory, resolution, user-agent, device-type, OS version, etc. -~~**UnrealCppSdk specific changes:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealCppSdk specific changes:**~~ (UPDATED : This SDK is deprecated. For the new unreal SDK, refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~Updated to Unreal 4.17~~ -- ~~Split apart into 3 separate plugins, each with different functionality~~ -- ~~Pretty significant upgrades overall~~ +- ~~Split apart into three separate plugins, each with different functionality~~ +- ~~Significant upgrades overall~~ ## 170828 -Date: 2017-08-28 +Date: August 28, 2017 ### Client API changes -- ~~client.[GetCurrentGames].[result].Games[i].GameServerState has been deprecated, and replaced with [GameServerStateEnum]~~. +- ~~client.[GetCurrentGames].[result].Games[i].GameServerState is deprecated, and replaced with [GameServerStateEnum]~~. ~~- GameServerState was serialized as an integer, which was an error. The new field is a proper enum-string.~~ (UPDATED: This is deprecated. See [Servers](../multiplayer/servers/index.md)) ### Other API changes -- The following API methods have been deprecated on Admin and Server APIs. - - [GetActionsOnPlayersInSegmentTaskInstance](xref:titleid.playfabapi.com.admin.scheduledtask.getactionsonplayersinsegmenttaskinstance) - This has accidentally been labeled as deprecated, but that was an error which will be reverted. +- Deprecated the following API methods on Admin and Server APIs. + - [GetActionsOnPlayersInSegmentTaskInstance](xref:titleid.playfabapi.com.admin.scheduledtask.getactionsonplayersinsegmenttaskinstance) - This has accidentally been labeled as deprecated, but that was an error that is reverted. - [SendPushNotification](xref:titleid.playfabapi.com.server.accountmanagement.sendpushnotification) can now specify [TargetPlatforms](xref:titleid.playfabapi.com.server.accountmanagement.sendpushnotification#sendpushnotificationrequest) -- Added some clarifications for which parameters work on which platforms for [SendPushNotificationRequest](xref:titleid.playfabapi.com.server.accountmanagement.sendpushnotification#sendpushnotificationrequest) (Using parameters not supported for a target platform is not recommended). +- Added some clarifications for which parameters work on which platforms for [SendPushNotificationRequest](xref:titleid.playfabapi.com.server.accountmanagement.sendpushnotification#sendpushnotificationrequest) (Using parameters not supported for a target platform isn't recommended). - Added some info about [Shared Group](xref:titleid.playfabapi.com.client.sharedgroupdata.createsharedgroup) [restrictions](../community/associations/groups/using-shared-group-data.md) to the Shared Group documentation (specifically that they can't be used for anything like Guilds). - [Player Profiles](xref:titleid.playfabapi.com.client.accountmanagement.getplayerprofile#playerprofilemodel) can now store a player [contact email address](xref:titleid.playfabapi.com.client.accountmanagement.getplayerprofile#contactemailinfomodel). ### New PlayStream events -- [entity_created](../api-references/events/entity-created.md) -- [entity_logged_in](../api-references/events/entity-logged-in.md) +- [entity_created](../api-references/events/PlayerIdentity/entity-created.md) +- [entity_logged_in](../api-references/events/PlayerIdentity/entity-logged-in.md) ## 170814 -Date: 2017-08-14 +Date: August 14, 2017 ### API updates @@ -263,12 +263,12 @@ Date: 2017-08-14 ### CSharpSdk specific updates -- SDK now includes a file called [NewtonSoftJsonWrapper.cs](https://github.com/PlayFab/CSharpSDK/blob/master/PlayFabSDK/source/Json/NewtonsoftWrapper.cs) which will let you swap out our included SimpleJson serializer with the NewtonSoft nuget package. +- SDK now includes a file called [NewtonSoftJsonWrapper.cs](https://github.com/PlayFab/CSharpSDK/blob/master/PlayFabSDK/source/Json/NewtonsoftWrapper.cs), which will let you swap out our included SimpleJson serializer with the NewtonSoft NuGet package. - The file includes instructions on how to use it. ## 170807 -Date: 2017-08-07 +Date: August 7, 2017 ### New API methods @@ -276,7 +276,7 @@ Date: 2017-08-07 ### Deprecated API methods -- These API methods never worked as fully and completely as they were supposed to. In an effort to clean this up, we've started over, and built the new [DeletePlayer](xref:titleid.playfabapi.com.admin.accountmanagement.deleteplayer) API above, and these are deprecated: +- These API methods never worked as fully and completely as they were supposed to. To clean this up, we've started over, and built the new [DeletePlayer](xref:titleid.playfabapi.com.admin.accountmanagement.deleteplayer) API in the preceding section, and these are deprecated: - `admin.ResetUsers` - `admin.DeleteUsers` @@ -286,29 +286,29 @@ Date: 2017-08-07 ### PlayStream events -- New Event: [auth_token_validated](../api-references/events/auth-token-validated.md) -- New Event: [player_removed_title](../api-references/events/player-removed-title.md) -- New Event: [player_updated_contact_email](../api-references/events/player-updated-contact-email.md) -- New Event: [player_verified_contact_email](../api-references/events/player-verified-contact-email.md) -- New Event: [sent_email](../api-references/events/sent-email.md) (Still in beta, but events are already public) -- New Field in Event: [player_realmoney_purchase](../api-references/events/player-realmoney-purchase.md).TransactionId +- New Event: [auth_token_validated](../api-references/events/PlayerIdentity/auth-token-validated.md) +- New Event: [player_removed_title](../api-references/events/PlayerIdentity/player-removed-title.md) +- New Event: [player_updated_contact_email](../api-references/events/PlayerIdentity/player-updated-contact-email.md) +- New Event: [player_verified_contact_email](../api-references/events/PlayerIdentity/player-verified-contact-email.md) +- New Event: [sent_email](../api-references/events/TitleCommunications/sent-email.md) (Still in beta, but events are already public) +- New Field in Event: [player_realmoney_purchase](../api-references/events/Player/player-realmoney-purchase.md).TransactionId ~~**LumberyardSdk changes:**~~ - ~~**UPGRADE WARNING:** This SDK is no longer compatible with previous versions of Lumberyard.~~ -- ~~This release of PlayFab LumberyardSdk no longer works with Lumberyard version 1.3. It has been upgraded and now targets Lumberyard 1.9. We will very likely have it targeting 1.10 in the near future, but again without backwards compatibility to 1.9 or earlier. See [our blog](https://blog.playfab.com/blog/cpp-sdk-updates) for details.~~ +- ~~This release of PlayFab LumberyardSdk no longer works with Lumberyard version 1.3. It's upgraded and now targets Lumberyard 1.9. We'll likely have it targeting 1.10 soon, but again without backwards compatibility to 1.9 or earlier. See [our blog](https://blog.playfab.com/blog/cpp-SDK-updates) for details.~~ -~~**UnrealCppSdk:**~~ (**UPDATED**: This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)). +~~**UnrealCppSdk:**~~ (**UPDATED**: This SDK is deprecated. For the new unreal SDK, refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)). - -~~**Unreal SDK:**~~ (**UPDATED**: This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**Unreal SDK:**~~ (**UPDATED**: This SDK is deprecated. For the new unreal SDK, refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~The PlayFab UnrealBlueprintSdk is now rebranded as the "Unreal SDK"~~ -- ~~Unreal SDK has been updated to 4.16, with some minor fixes~~ +- ~~Unreal SDK is updated to 4.16, with some minor fixes~~ - ~~We're also removing support for older versions of Unreal, which require older versions of Visual Studio~~ -- ~~We now support 4.14 thru 4.16~~ +- ~~We now support 4.14 through 4.16~~ - ~~Your project may continue working for older versions of Visual Studio, but we can only support and test Visual Studio 2015 and later~~ - ~~Read [our blog](https://blog.playfab.com/blog/visual-studio-2013-deprecation-notice) for more info~~ @@ -319,11 +319,11 @@ Date: 2017-08-07 ## 170710 -Date: 2017-07-10 +Date: July 10, 2017 ### API changes -- An Enterprise feature for double-encrypted logins has been released from beta, and is now live. +- Released an Enterprise feature for double-encrypted logins from beta, and it's now live. - **New API methods:** - admin.[CreatePlayerSharedSecret](xref:titleid.playfabapi.com.admin.authentication.createplayersharedsecret) - admin.[DeletePlayerSharedSecret](xref:titleid.playfabapi.com.admin.authentication.deleteplayersharedsecret) @@ -338,17 +338,17 @@ Date: 2017-07-10 ### SDK breaking change -- admin.[SetupPushNotificationRequest](xref:titleid.playfabapi.com.admin.title-widedatamanagement.setuppushnotification#setuppushnotificationrequest).Platform is now defined as an enum instead of a string. This is not a breaking change to the API (as enums are transmitted as strings), but it will require some users to convert their strings to the enum values in their code. +- admin.[SetupPushNotificationRequest](xref:titleid.playfabapi.com.admin.title-widedatamanagement.setuppushnotification#setuppushnotificationrequest).Platform is now defined as an enum instead of a string. This isn't a breaking change to the API (as enums are transmitted as strings), but it requires some users to convert their strings to the enum values in their code. ### Changes in all SDKs -- Minor SDK Breaking Change: Most SDKs have lost an optional field in multiple requests called UseSpecificVersion, which was an alternate way to define the adjacent Version field as null. Not all languages have the capability to define an integer as null in the request, and this field was only meant to be useful in relevant SDKs (Specifically Unreal). If you are using this field, just remove it, and set the adjacent Version field to null when appropriate. +- Minor SDK Breaking Change: Most SDKs have lost an optional field in multiple requests called UseSpecificVersion, which was an alternate way to define the adjacent Version field as null. Not all languages have the capability to define an integer as null in the request, and this field was only meant to be useful in relevant SDKs (Specifically Unreal). If you're using this field, just remove it, and set the adjacent Version field to null when appropriate. ### Unity EditorExtensions update -- The flags panel has been updated. +- Updated the flags panel. - `ENABLE/DISABLE_IDFA` flag can be toggled now. -- Displays non-PlayFab flags, and allows you to remove them (use with caution, don't remove flags you need). +- Displays non-PlayFab flags, and lets you remove them (use with caution, don't remove flags you need). ### SDK Dependency updates @@ -357,38 +357,38 @@ Date: 2017-07-10 - [ActionScriptSDK](https://github.com/PlayFab/ActionScriptSDK) tested with AirSDK v26. - SDK unchanged, example updated to target v26. - [Cocos2d-xSDK](https://github.com/PlayFab/Cocos2d-xSDK) built, and tested with Cocos 3.15.1. -- Cocos 3.14->3.15 contained changes that broke our example, which in turn meant the example had to be updated. The example still works with 3.13 thru 3.15, but the example probably won't work with older versions of Cocos SDK unchanged, and should continue to work with most of the latest 3.X Cocos versions. +- Cocos 3.14->3.15 contained changes that broke our example, which in turn meant the example had to be updated. The example still works with 3.13 through 3.15, but the example might not work with older versions of Cocos SDK unchanged, and should work with most of the latest 3.X Cocos versions. ## 170612 -Date: 2017-06-12 +Date: June 12, 2017 ### Documentation changes - Many small revisions to dozens of API methods for clarity -- Several documentation-groupings, each which only contained a single API method, have been merged into a single group called "Platform Specific Methods". -- The "Matchmaking APIs" group has been renamed to "Matchmaking" to be consistent with other groups. +- Merged several documentation-groupings, each of which only contained a single API method, into a single group called "Platform Specific Methods". +- Renamed the "Matchmaking APIs" group to "Matchmaking" to be consistent with other groups. - Many length-restricted string fields now describe the allowed ranges. ### Changes in all SDKs -- Lots of broken links in all SDK readme's have been updated and fixed. +- Updated and fixed lots of broken links in all SDK READMEs. ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - We now support multiple versions of the Android API and Google Play Services. Read more details [here](https://github.com/PlayFab/UnitySDK/tree/master/Packages). - - This concludes the planned changes to the Unity + Android Push-Plugin for now. Please let us know if you have any additional requests [here](https://community.playfab.com/questions/10840/android-plugin-upgrade-discussion.html). + - This concludes the planned changes to the Unity + Android Push-Plugin for now. Let us know if you have any more requests [here](https://community.playfab.com/questions/10840/android-plugin-upgrade-discussion.html). ## 170530 -Date: 2017-05-30 +Date: May 30, 2017 ### API changes -- **BREAKING CHANGE:** In server.[ReportPlayer](xref:titleid.playfabapi.com.server.playeritemmanagement.reportplayer), the `titleId` field in [ReportPlayerServerRequest](xref:titleid.playfabapi.com.server.playeritemmanagement.reportplayer#reportplayerserverrequest) has been immediately removed (not merely deprecated). All reports will now go to their own title, and cannot report to another title. +- **BREAKING CHANGE:** In server.[ReportPlayer](xref:titleid.playfabapi.com.server.playeritemmanagement.reportplayer), we immediately removed the `titleId` field in [ReportPlayerServerRequest](xref:titleid.playfabapi.com.server.playeritemmanagement.reportplayer#reportplayerserverrequest) (not merely deprecated). All reports now go to their own title, and can't report to another title. - This had to be a breaking change as it was otherwise a mild cross-title exploit. [Contact us](https://community.playfab.com/questions/ask.html) if you need assistance with this change. -- In client.[ReportPlayer](xref:titleid.playfabapi.com.client.accountmanagement.reportplayer) and server.[ReportPlayer](xref:titleid.playfabapi.com.server.playeritemmanagement.reportplayer), result.Updated has been deprecated in both cases. It was always true, and the API Call would always return an error if the player was over the report limit. This error condition has been updated to be OverLimit to match other limits. +- In client.[ReportPlayer](xref:titleid.playfabapi.com.client.accountmanagement.reportplayer) and server.[ReportPlayer](xref:titleid.playfabapi.com.server.playeritemmanagement.reportplayer), we deprecated result.Updated in both cases. It's always true, and the API Call returns an error if the player is over the report limit. We changed this error condition to OverLimit to match other limits. - All [login methods](xref:titleid.playfabapi.com.client.authentication) can now return a [player profile object](xref:titleid.playfabapi.com.client.authentication.loginwithandroiddeviceid#playerprofilemodel), if requested, which contains information previously only available to leaderboard results. ### New API methods @@ -405,81 +405,81 @@ Date: 2017-05-30 - gameserverhost_started - gameserverhost_stopped -- [player_set_profile_property](../api-references/events/player-set-profile-property.md) +- [player_set_profile_property](../api-references/events/Player/player-set-profile-property.md) ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - Our Android Push plugin has been overhauled. + - Overhauled our Android Push plugin. - [Blog Post](https://blog.playfab.com/blog/push-upgrade-5-22) - [New/Updated Guide](../live-service-management/game-configuration/title-communications/push-notifications/push-notifications-for-android.md) ### CSharpSDK specific changes - [CSharpSDK](https://github.com/PlayFab/CSharpSDK) - - It is now possible to specify extra headers that will be injected into an API request. + - It's now possible to specify extra headers that are injected into an API request. - This is an Enterprise-Only feature, specifically for double-encrypted login requests. ## 170508 -Date: 2017-05-08 +Date: May 8, 2017 ### API changes - **BREAKING CHANGE:** - - [ExecuteCloudScript](xref:titleid.playfabapi.com.client.server-sidecloudscript.executecloudscript) will not serialize the return value of your call, if it is too large. - - [ExecuteCloudScript](xref:titleid.playfabapi.com.client.server-sidecloudscript.executecloudscript) will not serialize the logs for your call, if they are too large. -- Under either of these conditions, the call will still return 200/successful, but the FunctionResult and/or Logs properties will be null. + - [ExecuteCloudScript](xref:titleid.playfabapi.com.client.server-sidecloudscript.executecloudscript) doesn't serialize the return value of your call if it's too large. + - [ExecuteCloudScript](xref:titleid.playfabapi.com.client.server-sidecloudscript.executecloudscript) doesn't serialize the logs for your call if they're too large. +- Under either of these conditions, the call still returns 200/successful, but the FunctionResult and/or Logs properties are null. ### PlayStream event changes -- [player_vc_item_purchased](../api-references/events/player-vc-item-purchased.md) and [character_vc_item_purchased](../api-references/events/character-vc-item-purchased.md) now contain a StoreId parameter indicating which store was used to make a purchase. +- [player_vc_item_purchased](../api-references/events/Player/player-vc-item-purchased.md) and [character_vc_item_purchased](../api-references/events/Character/character-vc-item-purchased.md) now contain a StoreId parameter indicating which store was used to make a purchase. - **New event:** - - [title_profile_view_constraints_changed](../api-references/events/title-profile-view-constraints-changed.md) + - [title_profile_view_constraints_changed](../api-references/events/PlayerIdentity/title-profile-view-constraints-changed.md) ### CSharpSDK updates - [CSharpSDK](https://github.com/PlayFab/CSharpSDK) - - Some unused source files in [CSharpSDK](https://github.com/PlayFab/CSharpSDK) have been deleted. - - This should not affect any existing projects, or the Nuget package, as those files were not referenced by the Visual Studio Solution. + - Deleted some unused source files in [CSharpSDK](https://github.com/PlayFab/CSharpSDK). + - This shouldn't affect any existing projects, or the NuGet package, as those files weren't referenced by the Visual Studio Solution. ### Postman collection update -- Several common request parameters now utilize environment variables. +- Several common request parameters now use environment variables. - Specifically, TitleId={{TitleId}}, PlayFabId={{PlayFabId}}, CharacterId={{CharacterId}}, and CatalogVersion={{PrimaryCatalogName}} ## 170424 -Date: 2017-04-24 +Date: April 24, 2017 ### SDK hotfix release - **[JavaSDK](https://github.com/PlayFab/JavaSDK) Updates:** - We now publish Jar files for the SDK, one for code, and one for Java docs, which you can import into your Java project instead of copy-pasting code. Thanks to Will Iverson for helping us improve our [JavaSDK](https://github.com/PlayFab/JavaSDK) usability - **UnityEditorExtensions updates:** - - We have resolved some install-time exceptions. Specifically it is no longer required that you restart Unity after a first-time install. + - We've resolved some install-time exceptions. Specifically it's no longer required that you restart Unity after a first-time install. - Additionally, an issue where the Client API was sometimes disabled inappropriately is now fixed. (edited) -- ~~**UnrealCppSdk Updates:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +- ~~**UnrealCppSdk Updates:**~~ (UPDATED : This SDK is deprecated. For the new unreal SDK, refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~The titleId is now available from the Plugin interface~~ ## 170411 -Date: 2017-04-11 +Date: April 11, 2017 ### API changes -- New Enterprise Feature: Additional login encryption -- You can utilize the Policy API methods to enforce Login Calls can require a second layer of encryption +- New Enterprise Feature: More login encryption +- You can use the Policy API methods to enforce Login Calls can require a second layer of encryption - See: [UpdatePolicy](xref:titleid.playfabapi.com.admin.authentication.updatepolicy) , specifically [UpdatePolicyRequest](xref:titleid.playfabapi.com.admin.authentication.updatepolicy#updatepolicyrequest).[Statements](xref:titleid.playfabapi.com.admin.authentication.updatepolicy#permissionstatement).[ApiConditions](xref:titleid.playfabapi.com.admin.authentication.updatepolicy#apicondition) -- This feature is still partially in beta, and activating it is not suggested (yet - Coming Soon!) +- This feature is still partially in beta, and activating it isn't suggested (yet - Coming Soon!) ### New PlayStream events -- [player_receipt_validation](../api-references/events/player-receipt-validation.md) +- [player_receipt_validation](../api-references/events/Player/player-receipt-validation.md) ### UnitySDK specific changes -- It is now possible to specify extra headers that will be injected into an API request (This is required for the encrypted login calls above). +- It's now possible to specify extra headers that are injected into an API request (This is required for the encrypted login calls in the preceding section). ### UnityEditorExtensions specific changes @@ -487,56 +487,56 @@ Date: 2017-04-11 ## 170406 -Date: 2017-04-06 +Date: April 6, 2017 ### Hot Fix for Unity Android Push plugin - Fixed Android 7.0+ Crash Bug. -- Fixed Android missing Large Icon support ( Lollipop + ). -- Fixed Android Small Icon support on Android 7.0+ ( now supports \_transparent.png ). +- Fixed Android missing Large Icon support (Lollipop+). +- Fixed Android Small Icon support on Android 7.0+ (now supports \_transparent.png). ## 170403 -Date: 2017-04-03 +Date: April 3, 2017 ### API changes - **Client & Server Leaderboard Methods:** Get-Leaderboard methods (such as client.[GetLeaderboard](xref:titleid.playfabapi.com.client.playerdatamanagement.getleaderboard)) previously gained new non-nullable parameters Version and UseSpecificVersion. The requirement that they were non-nullable was an API-breaking change. We have updated these properties to be fully optional. -- **Client API:** The Items field of [GetPurchaseResult](xref:titleid.playfabapi.com.client.playeritemmanagement.getpurchase#getpurchaseresult) will be deprecated: This portion of the result is often incorrect or incomplete. It will eventually be replaced with a fully functional parameter. +- **Client API:** The Items field of [GetPurchaseResult](xref:titleid.playfabapi.com.client.playeritemmanagement.getpurchase#getpurchaseresult) is deprecated: This portion of the result is often incorrect or incomplete. It's eventually replaced with a fully functional parameter. ### New PlayStream events - `player_display_name_filtered` -~~**Unreal Specific Changes:**~~ (**UPDATED** : This SDK has been deprecated. For the new Unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**Unreal Specific Changes:**~~ (**UPDATED** : This SDK is deprecated. For the new Unreal SDK, refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) -- ~~UnrealCppSdk: An issue where PlayFab settings such as TitleId were lost when publishing a build has been fixed. -Both SDKs have been tested and verified working with Unreal 4.15~~ +- ~~UnrealCppSdk: An issue where PlayFab settings such as TitleId were lost when publishing a build is fixed. +Both SDKs are tested and verified working with Unreal 4.15~~ ### JavaSDK specific changes - [JavaSDK](https://github.com/PlayFab/JavaSDK) - - [JavaSDK](https://github.com/PlayFab/JavaSDK) folder structure and testing has been restructured. + - Restructured [JavaSDK](https://github.com/PlayFab/JavaSDK) folder structure and testing. - The internal folder structure of the repo has changed a bit to accommodate Maven best practices. - Dependencies are now Maven controlled and no longer included with the SDK. - - Our internal automated testing has been converted to Maven command line. - - Our SDK is NOT available on Maven Central, as that effort has faltered. There is no ETA for completion at this time. + - Converted our internal automated testing to Maven command line. + - Our SDK isn't available on Maven Central, as that effort has faltered. There's no ETA for completion at this time. ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - Internal Unity version for testing and building asset bundles updated to 5.6.0. Our Unity SDK remains compatible with all versions of Unity from 4.7 thru 5.6. - - A compile issue with `UnityEditorExtensions` in Unity 5.6 has been fixed. + - Internal Unity version for testing and building asset bundles updated to 5.6.0. Our Unity SDK remains compatible with all versions of Unity from 4.7 through 5.6. + - Fixed a compile issue with `UnityEditorExtensions` in Unity 5.6. ## 170223 -Date: 2017-02-22 +Date: February 22, 2017 ### API changes - PlayFab leaderboards now store an avatar url for every player. This can be used to reference a player image for leaderboard entries. -- All leaderboard APIs can now fetch a specific version of the leaderboard. This is for titles which are set to use Resetting Leaderboards. -- Leaderboard entries now contain the [PlayerProfile](xref:titleid.playfabapi.com.client.accountmanagement.getplayerprofile#playerprofilemodel) which can be used to display more detailed leaderboards without additional API calls +- All leaderboard APIs can now fetch a specific version of the leaderboard. This is for titles that are set to use Resetting Leaderboards. +- Leaderboard entries now contain the [PlayerProfile](xref:titleid.playfabapi.com.client.accountmanagement.getplayerprofile#playerprofilemodel), which can be used to display more detailed leaderboards without extra API calls - PlayFab can now authenticate clients using Windows Hello and validate Windows store receipts ### New APIs @@ -552,7 +552,7 @@ Date: 2017-02-22 ``` ### New PlayStream events -- [player_changed_avatar](../api-references/events/player-changed-avatar.md) +- [player_changed_avatar](../api-references/events/PlayerIdentity/player-changed-avatar.md) ### WindowsSDK specific changes @@ -564,41 +564,41 @@ Date: 2017-02-22 ## 170130 -Date: 2017-01-29 +Date: January 29, 2017 ### Breaking changes -- The folder structure for [JavaScriptSDK](https://github.com/PlayFab/JavaScriptSDK) and [NodeSDK](https://github.com/PlayFab/NodeSDK) has been changed with today's major release. This may result in some broken connections for your project when you upgrade. (File names and file contents have not changed. New **TypeScript** files now exist, which did not exist before.) +- Changed the folder structure for [JavaScriptSDK](https://github.com/PlayFab/JavaScriptSDK) and [NodeSDK](https://github.com/PlayFab/NodeSDK) with today's major release. This may result in some broken connections for your project when you upgrade. (File names and file contents didn't change. New **TypeScript** files now exist, which didn't exist before.) ### API changes -- Added clarifying documentation to CDN APIs. Specifically mentioning that the CDN is not part of our free service. +- Added clarifying documentation to CDN APIs. Specifically mentioning that the CDN isn't part of our free service. - Google login fixes (Blog Post Pending). ### New PlayStream events - `developer_logged_in` - `developer_registered` -- [studio_created](../api-references/events/studio-created.md) -- [studio_user_added](../api-references/events/studio-user-added.md) -- [studio_user_invited](../api-references/events/studio-user-invited.md) -- [studio_user_removed](../api-references/events/studio-user-removed.md) +- [studio_created](../api-references/events/DeveloperIdentity/studio-created.md) +- [studio_user_added](../api-references/events/DeveloperIdentity/studio-user-added.md) +- [studio_user_invited](../api-references/events/DeveloperIdentity/studio-user-invited.md) +- [studio_user_removed](../api-references/events/DeveloperIdentity/studio-user-removed.md) ### JavaScriptSDK specific changes - [JavaScriptSDK](https://github.com/PlayFab/JavaScriptSDK) - - Release day for a major upgrade! Version number updated to 1.0. + - Release day for a major upgrade! Version number updated to 1.0. - TypeScript integration! - - Repository cleanup: Separating the sdk files from the example files. - - Our example project has been converted to TypeScript. + - Repository cleanup: Separating the SDK files from the example files. + - Converted our example project to TypeScript. - See [our blog](https://blog.playfab.com/blog/typescript/)! ### NodeSDK specific changes - [NodeSDK](https://github.com/PlayFab/NodeSDK) - - Release day for a major upgrade! Version number updated to 1.0 + - Release day for a major upgrade! Version number updated to 1.0 - TypeScript integration! - - Our example project has been converted to TypeScript + - Converted our example project to TypeScript - See [our blog](https://blog.playfab.com/blog/typescript/)! ### CloudScript examples @@ -607,14 +607,14 @@ Date: 2017-01-29 - TypeScript integration! - See [our blog](https://blog.playfab.com/blog/typescript/)! - And [new repository](https://github.com/PlayFab/SdkTestingCloudScript)! -- We will be expanding this repository over time. +- We're expanding this repository over time. ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - Fixed an issue where where **JsonWrapper** did not work as expected in all cases. + - Fixed an issue where **JsonWrapper** doesn't work as expected in all cases. - See our forum post for details: - - All of the following deprecated wrapper classes have been removed in favor of `PlayFab.Json.JsonWrapper`: + - Removed all of the following deprecated wrapper classes in favor of `PlayFab.Json.JsonWrapper`: - `PlayFab.Json.JsonConvert` (Use `PlayFab.Json.JsonWrapper`) - `PlayFab.Json.SimpleJson` (Use `PlayFab.Json.JsonWrapper` or `PlayFab.Json.PlayFabSimpleJson`) - `PlayFab.SimpleJson` (Use `PlayFab.Json.JsonWrapper` or `PlayFab.Json.PlayFabSimpleJson`) @@ -622,16 +622,16 @@ Date: 2017-01-29 ### Unity Editor Extensions -- Resolved an issue where the PlayFab panel will re-load infinitely if your account cannot view any studios. -- Resolved an issue where `PlayFabSharedSettings` (Scriptable Object) would sometimes not save properly if you picked your title from the PlayFab panel. +- Resolved an issue where the PlayFab panel will re-load infinitely if your account can't view any studios. +- Resolved an issue where `PlayFabSharedSettings` (Scriptable Object) doesn't save properly if you pick your title from the PlayFab panel. ## 170109 -Date: 2017-01-08 +Date: January 8, 2017 ### Breaking changes -- Libs in older versions of WindowsSDK have been removed, and must be re-created in Visual Studio. Those libs never worked in vs2015, so it's highly suggested you just update to the latest WindowsSDK, published last week. +- Removed libs in older versions of WindowsSDK, and they must be re-created in Visual Studio. Those libs never worked in vs2015, so it's highly suggested you just update to the latest WindowsSDK, published last week. ### API changes @@ -644,26 +644,26 @@ Date: 2017-01-08 ### SDKGenerator specific changes - [SDKGenerator](https://github.com/PlayFab/SDKGenerator) - - The [ActionScriptSDK](https://github.com/PlayFab/ActionScriptSDK) build script was inconsistent from the other SDKs. The [SDKGenerator](https://github.com/PlayFab/SDKGenerator) commands that build [ActionScriptSDK](https://github.com/PlayFab/ActionScriptSDK) have been simplified to match other SDKs. (No changes to the SDK itself.) + - The [ActionScriptSDK](https://github.com/PlayFab/ActionScriptSDK) build script was inconsistent from the other SDKs. We simplified the [SDKGenerator](https://github.com/PlayFab/SDKGenerator) commands that build [ActionScriptSDK](https://github.com/PlayFab/ActionScriptSDK) to match other SDKs. (No changes to the SDK itself.) ### UnitySdk specific changes - [UnitySdk](https://github.com/PlayFab/UnitySDK) - Some public elements in PlayFabSettings have gained Obsolete tags: `PlayFabSettings.PlayFabSharedSettings` `PlayFabSettings.DefaultPlayFabApiUrl` `PlayFabSettings.GetSharedSettingsObject()` `PlayFabSettings.ProductionEnvironmentUrl` -These will be made private after a transition period. +These are made private after a transition period. ### WindowsSDK specific changes -- GitHub repo has been BFG'd, and all large files have been removed from the history. Please delete your clone or fork, and re-create it so that your history is clean. +- BFG'd the GitHub repo, and removed all large files from the history. Delete your clone or fork, and re-create it so that your history is clean. ## 170102 -Date: 2017-01-01 +Date: January 1, 2017 ### API changes -- `Client/GetUserCombinedInfo` has transitioned to fully obsolete, and has been removed from the SDK and documentation. +- `Client/GetUserCombinedInfo` transitioned to fully obsolete, and we removed it from the SDK and documentation. ### Cocos2d-xSDK specific changes @@ -675,15 +675,15 @@ Date: 2017-01-01 ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - We have internally updated to Unity 5.5, and our **.unitypackage** files are built using this version + - We've internally updated to Unity 5.5, and our **.unitypackage** files are built using this version - As always, we continue to support *all Unity versions 4.7 and higher*. - - Added static constructors to many static classes, in order to solidify the initialization sequence in **Mono2x** compiler. This should resolve some of the `PlayFabSharedSettings` issues we've been seeing in iOS. + - Added static constructors to many static classes, to solidify the initialization sequence in **Mono2x** compiler. This should resolve some of the `PlayFabSharedSettings` issues we've been seeing in iOS. - **IDFA/ADID** will now work properly for Unity 5.6 beta. - - **KNOWN ISSUE:** Unity 5.6 beta builds do not work on **Windows Server** (**OS**), which includes PlayFab game-server hosting. Please contact Unity if this affects you. + - **KNOWN ISSUE:** Unity 5.6 beta builds don't work on **Windows Server** (**OS**), which includes PlayFab game-server hosting. Contact Unity if this affects you. ### WindowsSDK specific changes - Release day for a major upgrade! -- Blog Post: [Windows SDK Update Released](https://api.playfab.com/blog/windows-sdk-update-released) +- Blog Post: [Windows SDK Update Released](https://api.playfab.com/blog/windows-SDK-update-released) - Upgrade Guide: [PlayFab WindowsSdk v0.x -> v1.x Upgrade guide](https://github.com/PlayFab/WindowsSdk/blob/master/UpgradeGuide.md) diff --git a/playfab-docs/release-notes/2018.md b/playfab-docs/release-notes/2018.md index bf4f7bab0..b493cdf8f 100644 --- a/playfab-docs/release-notes/2018.md +++ b/playfab-docs/release-notes/2018.md @@ -6,7 +6,7 @@ ms.author: jenelleb ms.date: 07/12/2018 ms.topic: article ms.service: azure-playfab -keywords: playfab, development, release, apis, features +keywords: playfab, development, release, APIs, features ms.localizationpriority: medium --- @@ -14,12 +14,12 @@ ms.localizationpriority: medium ## 181218 -Date: 2018-12-18 +Date: December 18, 2018 ### XPlatCppSdk specific changes - [XPlatCppSdk](https://github.com/PlayFab/XPlatCppSdk) - -**SDK Breaking Change** : Updated the folder structure for the ``XPlatCppSdk`` repo. If you are using the SDK with project references, an update to vcxproj files path would be required. + -**SDK Breaking Change** : Updated the folder structure for the ``XPlatCppSdk`` repo. If you're using the SDK with project references, an update to vcxproj files path would be required. - Adding Xbox support to the `XPlatCppSdk`. Refer to the C++ quickstart for Xbox. - **New API** - Added `PlayFabEventApi` to support Heavyweight (low throughput) and Lightweight (high throughput) custom events. @@ -31,20 +31,20 @@ Date: 2018-12-18 ## 181204 -Date: 2018-12-04 +Date: December 4, 2018 ### XPlatCppSDK specific changes - [XPlatCppSDK](https://github.com/PlayFab/XPlatCppSDK) - Added support to build external dependencies. - - Updated nuget composition. This is not a breaking change. Added binaries for the external dependencies to the nuget and updated the properties sheet. + - Updated NuGet composition. This isn't a breaking change. Added binaries for the external dependencies to the NuGet and updated the properties sheet. - Bug fixes for **QoSAPI**. ### CSharpSDK specific changes - [CSharpSDK](https://github.com/PlayFab/CSharpSDK) - - Added .NET Standard 1.1/2.0 (plus .Net Core) support. - - Updated nuget composition. The package now contains binaries for .Net Standard 1.1/2.0 and portables also. + - Added .NET Standard 1.1/2.0 (plus .NET Core) support. + - Updated NuGet composition. The package now contains binaries for .NET Standard 1.1/2.0 and portables also. - Migrated VS project files to VS 2017 standard. ### UnitySDK specific changes @@ -55,25 +55,25 @@ Date: 2018-12-04 ## 181105 -Date: 2018-11-05 +Date: November 5, 2018 ### API changes - PlayFab now supports login and account-linking with `OpenID`. -- Additional XboxLive ID support, and enabling Xbox login via server. +- More XboxLive ID support, and enabling Xbox login via server. -In preparation for wider release of the service, we are rolling out PlayFab Multiplayer Servers 2.0 APIs. See [PlayFab Multiplayer Servers 2.0 (Thunderhead)](../multiplayer/servers/index.md) for more information +In preparation for wider release of the service, we're rolling out PlayFab Multiplayer Servers 2.0 APIs. See [PlayFab Multiplayer Servers 2.0 (Thunderhead)](../multiplayer/servers/index.md) for more information ## 181001 -Date: 2018-10-01 +Date: October 1, 2018 ### API changes -- A variety of deprecations have taken effect, and those elements have been removed from SDKs and documentation. - - Some Admin API methods related to unreleased features have been hidden. +- Various deprecations took effect, and we removed those elements from SDKs and documentation. + - Hid some Admin API methods related to unreleased features. - `server.DeleteUsers` deprecation has taken effect. - - A field deprecation for `ServerHostname`, spread across a variety of matchmaking related calls in admin, client, matchmaker, and server APIs has taken effect. `ServerIPV4Address` is the replacement. + - A field deprecation for `ServerHostname`, spread across various matchmaking related calls in admin, client, matchmaker, and server APIs has taken effect. `ServerIPV4Address` is the replacement. ### UnitySDK changes @@ -82,11 +82,11 @@ Date: 2018-10-01 ### All SDKs - The automated-build branch structure for GitHub repos is changing. - - The normal customer facing branches, "versioned" and "master" will be unchanged. + - The normal customer facing branches, "versioned" and "master" are unchanged. ## 180924 -Date: 2018-09-24 +Date: September 24, 2018 ### API changes @@ -95,7 +95,7 @@ Date: 2018-09-24 ## 180917 -Date: 2018-09-17 +Date: September 17, 2018 ### API changes @@ -103,12 +103,12 @@ Date: 2018-09-17 - Unreal Marketplace Plugin: - Updated Marketplace Plugin to include our Blueprint interface. - [New Unreal Engine quickstart guide](../sdks/unreal/quickstart.md) - - [View in Unreal Marketplace](https://www.unrealengine.com/marketplace/playfab-sdk) + - [View in Unreal Marketplace](https://www.unrealengine.com/marketplace/playfab-SDK) ## 180906 -Date: 2018-09-06 +Date: September 6, 2018 ### New API @@ -116,13 +116,13 @@ Date: 2018-09-06 ### New PlayStream event documentation -- [client_focus_change](../api-references/events/client-focus-change.md) -- [client_session_start](../api-references/events/client-session-start.md) -- [player_device_info](../api-references/events/player-device-info.md) +- [client_focus_change](../api-references/events/Session/client-focus-change.md) +- [client_session_start](../api-references/events/Session/client-session-start.md) +- [player_device_info](../api-references/events/PlayerIdentity/player-device-info.md) ## 180829 -Date: 2018-08-29 +Date: August 29, 2018 ### API changes @@ -142,14 +142,14 @@ Date: 2018-08-29 ## 180809 -Date: 2018-08-09 +Date: August 9, 2018 ### API group changes -- We have separated the Entity API Group into multiple new API Groups. +- We've separated the Entity API Group into multiple new API Groups. - This is a big SDK breaking change for anybody using the former Entity API. - See our [Upgrade Guide](../live-service-management/game-configuration/entities/entity-api-restructure-upgrade-tutorial.md)! -- (Please note, the links for blog and upgrade guide may not work yet, they're almost done.) +- (Note: the links for blog and upgrade guide may not work yet, they're almost done.) ### API changes @@ -162,9 +162,9 @@ Date: 2018-08-09 - client.[UnlinkFacebookInstantGamesId](xref:titleid.playfabapi.com.client.accountmanagement.unlinkfacebookinstantgamesid) (not ready to use yet) - server.[GetPlayFabIDsFromFacebookInstantGamesIds](xref:titleid.playfabapi.com.client.accountmanagement.getplayfabidsfromfacebookinstantgamesids) (not ready to use yet). - **New PlayStream Events** - - `title_hopper_config_updated` event renamed to [title_queue_config_updated](../api-references/events/title-queue-config-updated.md) + - `title_hopper_config_updated` event renamed to [title_queue_config_updated](../api-references/events/Matchmaking/title-queue-config-updated.md) - **General changes** - - The parameter `ServerAddress` in many models has been deprecated in favor of the new `ServerIPV4Address`. + - Deprecated the parameter `ServerAddress` in many models in favor of the new `ServerIPV4Address`. ### Unreal (multiple SDKs) Specific Changes @@ -178,13 +178,13 @@ Date: 2018-08-09 ### UnitySDK and CSharpSDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) and [CSharpSDK](https://github.com/PlayFab/CSharpSDK) - - Added a new structure called Plugin Manager. For now, this is just a foundation for future changes. Some old function signatures have been marked as obsolete, and should be updated. (No breaking changes though). + - Added a new structure called Plugin Manager. For now, this is just a foundation for future changes. We marked some old function signatures as obsolete, and you should update them. (No breaking changes though). - Found and resolved multiple issues with HTTPS.Put, which makes Entity Files more accessible on more platforms. - Bug fixes in the ScreenTime feature. ## 180716 -Date: 2018-07-16 +Date: July 16, 2018 ### UnitySDK changes @@ -196,13 +196,13 @@ Date: 2018-07-16 - [CSharpSDK](https://github.com/PlayFab/CSharpSDK) - Added [Plugin Manager API](https://github.com/PlayFab/CSharpSDK/blob/master/PluginManager.md) to C# SDK, to support optional custom implementations of JSON Serializer and HTTP client. - - ~~**UnrealCppSdk Changes:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) + - ~~**UnrealCppSdk Changes:**~~ (UPDATED : This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - - Unreal 4 C++ SDK is also published on [Unreal Marketplace!](https://www.unrealengine.com/marketplace/playfab-sdk) + - Unreal 4 C++ SDK is also published on [Unreal Marketplace!](https://www.unrealengine.com/marketplace/playfab-SDK) ## 180710 -Date: 2018-07-10 +Date: July 10, 2018 ### Unity hotfix release @@ -210,16 +210,16 @@ Date: 2018-07-10 ## 180709 -Date: 2018-07-09 +Date: July 9, 2018 ### Hotfix release - Fixing some minor issues with last week's deployments. -- Everything in last week's release notes should now actually work as promised. +- Everything in last week's release notes should now work as promised. ## 180706 -Date: 2018-07-06 +Date: July 6, 2018 ### API changes @@ -233,7 +233,7 @@ Date: 2018-07-06 ## 180705 -Date: 2018-07-05 +Date: July 5, 2018 ### API changes @@ -260,20 +260,20 @@ Date: 2018-07-05 ### XPlatCppSDK specific changes - [XPlatCppSDK](https://github.com/PlayFab/XPlatCppSdk) - - Large results will now be parsed correctly. + - Large results are now parsed correctly. ## 180618 -Date: 2018-06-18 +Date: June 18, 2018 ### API changes -- Added new error codes in a variety of API methods. +- Added new error codes in various API methods. - Multiple entity-related PlayStream events now describe their [EntityLineage](../api-references/events/data-types/entitylineage.md). ## 180528 -Date: 2018-05-28 +Date: May 28, 2018 ### API changes @@ -282,13 +282,13 @@ Date: 2018-05-28 - Admin.[DeleteMasterPlayerAccount](xref:titleid.playfabapi.com.admin.accountmanagement.deletemasterplayeraccount) - Admin.[ExportMasterPlayerData](xref:titleid.playfabapi.com.admin.accountmanagement.exportmasterplayerdata) - This is a part of the new GDPR launch. See our blog [here](https://blog.playfab.com/blog/gdpr) -- Updated Error codes in a variety of API methods +- Updated Error codes in various API methods - New PlayStream Event: - - [player_data_exported](../api-references/events/player-data-exported.md) + - [player_data_exported](../api-references/events/PlayerIdentity/player-data-exported.md) ## 180514 -Date: 2018-05-14 +Date: May 14, 2018 ### XPlatCppSDK specific changes @@ -297,31 +297,31 @@ Date: 2018-05-14 ## 180507 -Date: 2018-05-07 +Date: May 7, 2018 ### API changes - **New API Method:** - entity.[GetProfiles](xref:titleid.playfabapi.com.profiles.accountmanagement.getprofiles) - **New PlayStream Events:** - - [entity_executed_cloud_script](../api-references/events/entity-executed-cloud-script.md) + - [entity_executed_cloud_script](../api-references/events/CloudScript/entity-executed-cloud-script.md) - **Updated API Method:** - client.[RegisterPlayFabUser](xref:titleid.playfabapi.com.client.authentication.registerplayfabuser) now returns [result](xref:titleid.playfabapi.com.client.authentication.registerplayfabuser#registerplayfabuserresult).[EntityToken](xref:titleid.playfabapi.com.client.authentication.registerplayfabuser#entitytokenresponse) ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - `HttpWebRequest` certificate validation security has been improved. + - Improved `HttpWebRequest` certificate validation security. - No longer default to ignoring all certificates. - Customers are expected to implement their own certificate validation, or call `PlayFab.Internal.PlayFabWebRequest.SkipCertificateValidation()`. ### WindowsSdk specific changes - Fixed hundreds of Level 4 warnings. -- The version number published in `PlayFabSettings.cpp` has been corrected. -- Most previous versions will have all had the wrong version number embedded in-code, and in call headers. +- Corrected the version number published in `PlayFabSettings.cpp`. +- Most previous versions have all had the wrong version number embedded in-code, and in call headers. -### XPlatCppSDK has been created +### Created XPlatCppSDK - [XPlatCppSDK](https://github.com/PlayFab/XPlatCppSDK) - Currently in beta. @@ -329,25 +329,25 @@ Date: 2018-05-07 - May become a replacement to Windows SDK (At least several months away). - Upgrade should require almost no breaking changes. - Some `cpprestsdk` strings should be converted to `std::string`. - - Some `web::json::value` types have been converted to `json::value`. - - timestamps are not fully tested in Linux. + - Converted some `web::json::value` types to `json::value`. + - timestamps aren't fully tested in Linux. - NuGet package - Uses lighter weight dependencies - Specifically `jsoncpp` and curl, rather than `cpprestsdk`. - - Uses `std::string` everywhere, rather than a mix of 2 string types. + - Uses `std::string` everywhere, rather than a mix of two string types. - Adds Linux Support. ## 180414 -Date: 2018-04-14 +Date: April 14, 2018 -~~**UnrealCppSdk HotFix:**~~ (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-sdk)) +~~**UnrealCppSdk HotFix:**~~ (UPDATED : This SDK is deprecated. For the new unreal SDK, see [UnrealMarketplaceSDK](https://www.unrealengine.com/marketplace/playfab-SDK)) - ~~Issues were discovered in the Entity API release for UnrealCppSdk. These are hot fixed, and the Entity API should now work as expected.~~ ## 180409 -Date: 2018-04-09 +Date: April 9, 2018 ### API changes @@ -364,24 +364,24 @@ Date: 2018-04-09 ## 180403 -Date: 2018-04-03 +Date: April 3, 2018 -### Unreal SDKs updated to support v4.17 thru 4.19 +### Unreal SDKs updated to support v4.17 through 4.19 -- Removing support for UE 4.14 thru 4.16 (Please update!) +- Removing support for UE 4.14 through 4.16 (Update!) ## 180329 -Date: 2018-03-29 +Date: March 29, 2018 ### Unreal SDKs updated to support Entity APIs - Sorry for the delay! -- This release still targets UE 4.17, and not 4.18 or 4.19. We are in-progress working on updating versions. +- This release still targets UE 4.17, and not 4.18 or 4.19. We're in-progress working on updating versions. ## 180316 -Date: 2018-03-16 +Date: March 16, 2018 ### API changes @@ -415,7 +415,7 @@ Date: 2018-03-16 ## 180213 -Date: 2018-02-13 +Date: February 13, 2018 ### API changes @@ -426,12 +426,12 @@ Date: 2018-02-13 ### UnitySDK specific changes - [UnitySDK](https://github.com/PlayFab/UnitySDK) - - We are dropping support for older Unity versions, see our [blog post](https://blog.playfab.com/blog/unity-version-support). + - We're dropping support for older Unity versions, see our [blog post](https://blog.playfab.com/blog/unity-version-support). - Build files are now published using Unity version 2017.3.0f3. ## 180131 -Date: 2018-01-31 +Date: January 31, 2018 ### JavaSDK changes @@ -440,7 +440,7 @@ Date: 2018-01-31 ## 180129 -Date: 2018-01-29 +Date: January 29, 2018 ### UnitySDK specific changes @@ -450,18 +450,18 @@ Date: 2018-01-29 ## 180123 -Date: 2018-01-23 +Date: January 23, 2018 ### UnitySDK hotfix - [UnitySDK](https://github.com/PlayFab/UnitySDK) - PlayFab UnitySDK had an issue with Unity version 2017.1. - See the [forum post](https://community.playfab.com/questions/16734/error-cs1061-no-definition-for-sendwebrequesterror.html) for details. - - This has been resolved, PlayFab UnitySDK should work for all versions again. + - We resolved this. PlayFab UnitySDK should work for all versions again. ## 180122 -Date: 2018-01-22 +Date: January 22, 2018 ### API documentation update @@ -477,7 +477,7 @@ Date: 2018-01-22 - [NodeSDK](https://github.com/PlayFab/NodeSDK) - SDK Breaking Change: Require syntax for NodeSDK NPM package changed. - Major upgrade focused on NPM package. - - Formerly require statements did not follow the NPM convention, requiring multiple nonstandard require statements. + - Formerly require statements didn't follow the NPM convention, requiring multiple nonstandard require statements. - Now it requires a single require statement, and follows NPM conventions. - Major version number changed, this release is now 2.0. - 1.x to 2.x [Upgrade Guide](https://github.com/PlayFab/NodeSDK/blob/master/upgrade.md). @@ -488,22 +488,22 @@ Date: 2018-01-22 ## 180103 -Date: 2018-01-03 +Date: January 3, 2018 ### LuaSDK specific updates - [LuaSDK](https://github.com/PlayFab/LuaSDK)/Defold/Corona - Bug fix update. - - Some platforms were producing a malformed URL which could not be resolved. + - Some platforms were producing a malformed URL that couldn't be resolved. ## 180102 -Date: 2018-01-02 +Date: January 2, 2018 ### UnitySDK specific updates - [UnitySDK](https://github.com/PlayFab/UnitySDK) - Bug fix update. - - In order to avoid an issue with response headers, compression should be disabled for all device builds. This update makes that possible. + - To avoid an issue with response headers, compression should be disabled for all device builds. This update makes that possible. - Alternately, switching to Web Request will also avoid the issue. - - A new HTTP option has been added for Unity versions > 2017. + - Added a new HTTP option for Unity versions > 2017. From 243417b50d9dae538b31846875e04b26a93e77b5 Mon Sep 17 00:00:00 2001 From: Rachel Akisada <87677950+raakisad@users.noreply.github.com> Date: Fri, 20 Feb 2026 07:42:56 -0800 Subject: [PATCH 53/76] Raakisad update data connection (#2825) * Updated Data Connections for S3 * Updated to clarify preview status --- .../export-data/data-connection-overview.md | 4 ++ .../export-data/data-connection-quickstart.md | 51 +++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/playfab-docs/data-analytics/export-data/data-connection-overview.md b/playfab-docs/data-analytics/export-data/data-connection-overview.md index b65aaa26a..715a51788 100644 --- a/playfab-docs/data-analytics/export-data/data-connection-overview.md +++ b/playfab-docs/data-analytics/export-data/data-connection-overview.md @@ -38,3 +38,7 @@ For more optimized cost and data control, you can make use of data connections w ### Microsoft Fabric KQL database Data Connection You can utilize PlayFab's Data Connections service to distribute game events to Real-Time Analytics (RTA) databases, allowing you to generate near-real-time analytics and insights in Power BI or through KQL queries on your Microsoft Fabric workspace. + +### Amazon AWS S3 Data Connection (PREVIEW) + +The AWS S3 Data Connection provides a secure, scalable way to stream your PlayFab telemetry and event data directly into your own Amazon S3 bucket. Designed for reliability and high throughput workloads, it uses a robust pipeline to validate, transport, and land game data in an open, analytics ready format. By bringing your own AWS storage and IAM roles, you retain full control of data governance, encryption, access policies, lifecycle management, and cost visibility while enabling downstream workflows such as BI reporting, machine learning, and largescale data processing in your AWS environment. \ No newline at end of file diff --git a/playfab-docs/data-analytics/export-data/data-connection-quickstart.md b/playfab-docs/data-analytics/export-data/data-connection-quickstart.md index aa4cc1ecc..185c7a1dc 100644 --- a/playfab-docs/data-analytics/export-data/data-connection-quickstart.md +++ b/playfab-docs/data-analytics/export-data/data-connection-quickstart.md @@ -61,6 +61,57 @@ From PlayFab Game Manager: > [!Note] > To optimize your use of a Fabric KQL Data Connection and gain valuable insights into your game data, follow the tutorial on PlayFab and Microsoft Fabric Real-Time Analytics (RTA) for game creators: [PlayFab and Microsoft Fabric Real-Time Analytics (RTA) for game creators](../learn-data/reports/real-time-analytics-tutorial.md) +### Amazon Web Services S3 (PREVIEW) +From PlayFab Game Manager: +- Navigate to your Title +- Select Data from the menu on the left +- Select Data Connections from the Data tabs +- Select New Connection, new data connections configuration page is opened +- On the Destination type dropdown, select the AWS S3 option +- Give your Data Connection a name on the Name field +- Make sure the Enabled box is checked +- In the AWS console: + * Navigate to IAM + * Navigate to Identity Providers + * Select Add Provider + * Select OpenID Connect + * In the forum: + * For the provider URL, input https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/v2.0 + * For the Audience, input e12f8069-1801-4f61-9b5f-446d8bd57e8b + * Press Add Provider + * Navigate back to IAM + * Navigate to policies + * Select Create policy + * In the forum: + * Select JSON to switch to the JSON view + * Input the following policy: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::test/*", "arn:aws:s3:::test" ] } ] } + * Select Next + * Enter a name for your policy – take note of it for later + * Select Create policy + * Navigate back to IAM + * Navigate to Roles + * In the forum: + * Select Web Identity + * From the Identity provider dropdown, select the previously registered https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/v2.0 provider + * From the Audience dropdown, select the previously registered e12f8069-1801-4f61-9b5f-446d8bd57e8b audience + * Select Next + * In the search field, enter the name of the previously registered policy + * Check the box to the left of the policy + * Select Next + * Enter a name for the role – noting the name + * Select Create role + * Navigate to the general purpose S3 Bucket you want to use for your Connection + * Select Properties + * Scroll to the Tags section + * Select Add new Tag + * In the forum: + * For the key field, input playfab:titleids + * For the value field, input your playfab TitleID + * Select Save changes + * Ensure you have your S3 Bucket name, Role ARN, and S3 Bucket Region used in the prior steps. + * Enter those into the appropriate fields in the Game Manager. + + ## Manage connections The Data Connections overview (landing) page displays the available connections categorized as **enabled** or **disabled** as a **status**. You can have up to 3 enabled connections to the blob storage account at any time. From 2fc90013a6fed06d862fd070f864973352e39590 Mon Sep 17 00:00:00 2001 From: Ernesto Cortes Groman Date: Fri, 20 Feb 2026 09:42:24 -0800 Subject: [PATCH 54/76] Update EconomyV2 docs (#2827) Co-authored-by: Ernesto Cortes Groman --- .../economy-v2/catalog/bundles.md | 13 ++ .../economy-v2/catalog/real-money-prices.md | 170 ++++++++++++++++++ .../economy-v2/catalog/toc.yml | 2 + .../economy-v2/inventory/collections.md | 8 +- .../economy-v2/inventory/etags.md | 92 ++++++++++ .../economy-v2/inventory/index.md | 45 ++--- .../economy-v2/inventory/stacks.md | 2 +- .../economy-v2/inventory/toc.yml | 2 + .../economy-v2/overview.md | 6 + 9 files changed, 301 insertions(+), 39 deletions(-) create mode 100644 playfab-docs/economy-monetization/economy-v2/catalog/real-money-prices.md create mode 100644 playfab-docs/economy-monetization/economy-v2/inventory/etags.md diff --git a/playfab-docs/economy-monetization/economy-v2/catalog/bundles.md b/playfab-docs/economy-monetization/economy-v2/catalog/bundles.md index 43fcdaecd..d207d197a 100644 --- a/playfab-docs/economy-monetization/economy-v2/catalog/bundles.md +++ b/playfab-docs/economy-monetization/economy-v2/catalog/bundles.md @@ -90,3 +90,16 @@ Response: ... } ``` + +## Purchasing and Unpacking Bundles + +When a player purchases a bundle, the bundle is **automatically unpacked** — the individual items referenced in the bundle are granted directly to the player's inventory. The bundle itself does not appear as an inventory item. For more details on how bundles interact with inventory, see [Bundles in Inventory](../inventory/index.md#bundles). + +Bundles are also the primary mechanism for linking real-money marketplace products to in-game items. Each bundle can be linked to one or more marketplace products using `AlternateIds`. For more information, see [Fraud Prevention Quickstart](../fraud-prevention/quickstart.md). + +## See also + +* [Inventory Overview](../inventory/index.md) +* [Stores](stores.md) +* [Marketplace Integrations](../marketplace/marketplace-integrations/overview.md) +* [Fraud Prevention](../fraud-prevention/index.md) diff --git a/playfab-docs/economy-monetization/economy-v2/catalog/real-money-prices.md b/playfab-docs/economy-monetization/economy-v2/catalog/real-money-prices.md new file mode 100644 index 000000000..73ef6e12c --- /dev/null +++ b/playfab-docs/economy-monetization/economy-v2/catalog/real-money-prices.md @@ -0,0 +1,170 @@ +--- +title: Economy v2 Real Money Prices +author: ernestoc +description: Learn how to use RealMoneyPriceDetails to track real-money pricing for catalog items in PlayFab Economy v2. +ms.author: ernestoc +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, commerce, economy, pricing, real money, marketplace, revenue +ms.localizationpriority: medium +--- + +# Real money prices + +[!INCLUDE [notice](../../../includes/_economy-release.md)] + +Real money prices allow you to associate real-world currency values with catalog items on a per-marketplace basis. The `RealMoneyPriceDetails` property on a catalog item contains separate price dictionaries for each supported marketplace. This data is used by PlayFab to track revenue from marketplace transactions. + +## Overview + +When players purchase items through external marketplaces (Apple App Store, Google Play, Steam, Microsoft Store, Nintendo eShop, PlayStation Store), the transaction involves real-world money. By setting `RealMoneyPriceDetails` on your catalog items, PlayFab can: + +- **Track revenue** from marketplace redemptions in the [marketplace_transaction_redeemed](../../../api-references/events/Inventory/marketplace-transaction-redeemed.md) event. + +## Format + +`RealMoneyPriceDetails` is an object with a separate price dictionary for each supported marketplace: + +| Property | Type | Description | +| :--- | :--- | :--- | +| `AppleAppStorePrices` | `Dictionary` | The Apple App Store price amount per currency code. | +| `GooglePlayPrices` | `Dictionary` | The Google Play price amount per currency code. | +| `MicrosoftStorePrices` | `Dictionary` | The Microsoft Store price amount per currency code. | +| `NintendoEShopPrices` | `Dictionary` | The Nintendo eShop price amount per currency code. | +| `PlayStationStorePrices` | `Dictionary` | The PlayStation Store price amount per currency code. | +| `SteamPrices` | `Dictionary` | The Steam price amount per currency code. | + +Each dictionary maps a three-letter [ISO 4217](https://www.iso.org/iso-4217-currency-codes.html) currency code to a price in the **smallest currency unit** (for example, cents for USD). + +> [!NOTE] +> Only **United States Dollar (USD)** is currently supported as a currency code. + +You only need to populate the marketplace properties that are relevant to your title. For example, if your game is only on Google Play and the Apple App Store, you only need to set `GooglePlayPrices` and `AppleAppStorePrices`. + +### Price examples + +| Real-world price | Dictionary value | +| :--- | :--- | +| $0.99 USD | `{"USD": 99}` | +| $1.39 USD | `{"USD": 139}` | +| $4.99 USD | `{"USD": 499}` | +| $9.99 USD | `{"USD": 999}` | + +## Setting real money prices on a catalog item + +Real money prices are typically set on **bundles** that are linked to external marketplace products via `AlternateIds`. When a player redeems a marketplace purchase, PlayFab uses the `RealMoneyPriceDetails` value from the matching catalog bundle to record the revenue. + +### [API](#tab/setting-prices-api) + +You can set `RealMoneyPriceDetails` when creating or updating a catalog item using `CreateDraftItem` or `UpdateDraftItem`: + +```json +{ + "Item": { + "Type": "bundle", + "Title": { + "NEUTRAL": "Starter Pack" + }, + "ItemReferences": [ + { + "Id": "{{LaserSwordID}}", + "Amount": 1 + }, + { + "Id": "{{GoldCurrencyID}}", + "Amount": 500 + } + ], + "RealMoneyPriceDetails": { + "GooglePlayPrices": { + "USD": 499 + }, + "AppleAppStorePrices": { + "USD": 499 + }, + "SteamPrices": { + "USD": 499 + } + }, + "AlternateIds": [ + { + "Type": "GooglePlay", + "Value": "com.mygame.starterpack" + }, + { + "Type": "AppleAppStore", + "Value": "com.mygame.starterpack" + }, + { + "Type": "Steam", + "Value": "starterpack_001" + } + ] + }, + "Publish": true +} +``` + +You can also set different prices per marketplace if your pricing varies across stores: + +```json +"RealMoneyPriceDetails": { + "GooglePlayPrices": { + "USD": 499 + }, + "AppleAppStorePrices": { + "USD": 529 + }, + "MicrosoftStorePrices": { + "USD": 499 + } +} +``` + +### [Game Manager](#tab/setting-prices-game-manager) + +1. Navigate to **Economy** > **Catalog (V2)**. +2. Under the **Bundles** tab, select the bundle you want to edit or create a new one. +3. In the **Prices** section, configure the real money price for each marketplace. +4. In the **Marketplace Mapping** section, link the bundle to your external marketplace products. + +--- + +## How real money prices appear in events + +When a marketplace transaction is redeemed, the price for the corresponding marketplace is included in the [marketplace_transaction_redeemed](../../../api-references/events/Inventory/marketplace-transaction-redeemed.md) event as `RealMoneyPrices`. For example, a Google Play redemption: + +```json +{ + "Marketplace": "GooglePlay", + "MarketplaceTransctionId": "GPA.1234-5678-9012-34567", + "MarketplaceAlternateId": "com.mygame.starterpack", + "Amount": 1, + "ItemId": "{{BundleID}}", + "ItemType": "bundle", + "RealMoneyPrices": { + "USD": 499 + } +} +``` + +This event data can then be used for: + +- Custom analytics queries via the Insights Explorer + +## Best practices + +- **Always set `RealMoneyPriceDetails` on marketplace bundles.** This ensures accurate revenue tracking and analytics. +- **Use the smallest currency unit.** For USD, provide the price in cents (for example, `499` for $4.99). +- **Only populate the marketplaces you use.** You don't need to set prices for every marketplace — only the ones your title is published on. +- **Keep prices in sync with your marketplace listings.** When you update prices in an external marketplace, update the corresponding property in `RealMoneyPriceDetails` to maintain accurate reporting. +- **Set per-marketplace prices when they differ.** If your game is priced differently across stores, use the per-marketplace properties to reflect the actual price on each platform. + +## See also + +- [Economy v2 Bundles](bundles.md) +- [Stores](stores.md) +- [Fraud prevention quickstart](../fraud-prevention/quickstart.md) +- [Marketplace integrations](../marketplace/marketplace-integrations/overview.md) +- [marketplace_transaction_redeemed event](../../../api-references/events/Inventory/marketplace-transaction-redeemed.md) diff --git a/playfab-docs/economy-monetization/economy-v2/catalog/toc.yml b/playfab-docs/economy-monetization/economy-v2/catalog/toc.yml index 1dbf76b43..e220b8ae9 100644 --- a/playfab-docs/economy-monetization/economy-v2/catalog/toc.yml +++ b/playfab-docs/economy-monetization/economy-v2/catalog/toc.yml @@ -3,6 +3,8 @@ items: href: catalog-overview.md - name: Bundles href: bundles.md +- name: Real money prices + href: real-money-prices.md - name: Stores href: stores.md - name: Subscriptions diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/collections.md b/playfab-docs/economy-monetization/economy-v2/inventory/collections.md index 5a1d3941d..52bdff3e0 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/collections.md +++ b/playfab-docs/economy-monetization/economy-v2/inventory/collections.md @@ -26,7 +26,7 @@ Using the `GetInventoryCollectionIds` API, you can get a list of `CollectionId`s An example `GetInventoryCollectionIds` request: -```csharp +```json { "Entity": { "Type": "title_player_account", @@ -39,11 +39,11 @@ An example `GetInventoryCollectionIds` request: This request would return the following response: -```csharp +```json { "data": { "CollectionIds": [ - "default". + "default", "main_character" ] } @@ -74,7 +74,7 @@ For example, the following `AddInventoryItems` request uses the collectionId `ma } ``` -The above request would either create a brand new `main_character` inventory collection and add 10 of the item to it, or add 10 to the existing `main_character` inventory collection if it already existed. +The above request would either create a brand new inventory collection and add 10 of the item to it or add 10 to the existing `main_character` inventory collection if it already existed. ### DeleteInventoryCollection diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/etags.md b/playfab-docs/economy-monetization/economy-v2/inventory/etags.md new file mode 100644 index 000000000..18fcb72c4 --- /dev/null +++ b/playfab-docs/economy-monetization/economy-v2/inventory/etags.md @@ -0,0 +1,92 @@ +--- +title: Inventory ETags +author: wesjong +description: Using ETags for optimistic concurrency control with PlayFab Inventory APIs. +ms.author: wesjong +ms.date: 02/20/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, commerce, economy, monetization, inventory, etags, concurrency +ms.localizationpriority: medium +--- + +# Inventory ETags + +[!INCLUDE [notice](../../../includes/_economy-release.md)] + +ETags provide optimistic concurrency control for the PlayFab Inventory APIs. They allow you to detect and prevent conflicting writes when multiple sources are modifying a player's inventory simultaneously. + +## How Inventory ETags work + +Inventory read APIs such as `GetInventoryItems` return an `ETag` in the response body. This value represents the current version of the player's inventory collection. You can pass this value in subsequent write requests to ensure your changes don't conflict with other updates that may have occurred since you last read the inventory. + +### Example `GetInventoryItems` response with ETag + +```json +{ + "code": 200, + "status": "OK", + "data": { + "Items": [ + { + "Id": "0b440353-bdbc-48d8-8873-f0988c1f9d8b", + "StackId": "default", + "Amount": 10, + "Type": "catalogItem" + } + ], + "ETag": "1/MQ==" + } +} +``` + +## Supported HTTP Headers + +Inventory write APIs support ETags through the following HTTP headers: + +- **`X-PlayFab-Economy-If-Match`** — Pass a previously received `ETag` value. The request succeeds only if the inventory's current ETag matches. Use this when you need to guarantee that no other write has occurred since you last read the inventory. +- **`X-PlayFab-Economy-If-None-Match`** — Pass `*` as the value. The request succeeds only if the item does not already exist in the inventory. Useful for "create-only" scenarios. + +## Supported APIs + +The following Inventory write APIs support ETag headers: + +- [AddInventoryItems](/rest/api/playfab/economy/inventory/add-inventory-items) +- [SubtractInventoryItems](/rest/api/playfab/economy/inventory/subtract-inventory-items) +- [UpdateInventoryItems](/rest/api/playfab/economy/inventory/update-inventory-items) +- [PurchaseInventoryItems](/rest/api/playfab/economy/inventory/purchase-inventory-items) +- [DeleteInventoryItems](/rest/api/playfab/economy/inventory/delete-inventory-items) +- [TransferInventoryItems](/rest/api/playfab/economy/inventory/transfer-inventory-items) +- [ExecuteInventoryOperations](/rest/api/playfab/economy/inventory/execute-inventory-operations) + +## Usage Example + +A typical workflow using inventory ETags: + +1. Call `GetInventoryItems` and store the `ETag` from the response. +2. Perform your inventory write (for example, `AddInventoryItems`) and include the `X-PlayFab-Economy-If-Match` header with the stored `ETag`. +3. If the inventory has been modified by another request since you read it, the API returns a **412 Precondition Failed** error. In that case, re-read the inventory, get the latest `ETag`, and retry. + +``` +POST /Inventory/AddInventoryItems +Content-Type: application/json +X-EntityToken: +X-PlayFab-Economy-If-Match: 1/MQ== + +{ + "Entity": { + "Type": "title_player_account", + "Id": "ABCD12345678" + }, + "Item": { + "Id": "0b440353-bdbc-48d8-8873-f0988c1f9d8b" + }, + "Amount": 5 +} +``` + +## See also + +- [Inventory Overview](index.md) +- [Catalog ETags](../catalog/etags.md) +- [Idempotency](index.md#idempotency) diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/index.md b/playfab-docs/economy-monetization/economy-v2/inventory/index.md index eb248fe2e..f7fe4684c 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/index.md +++ b/playfab-docs/economy-monetization/economy-v2/inventory/index.md @@ -161,6 +161,14 @@ An example `PurchaseInventoryItems` request: > [!NOTE] > The `PurchaseInventoryItems` API is used for purchases with virtual currencies. For real-money purchases through external marketplaces (Apple App Store, Google Play, Steam, Microsoft Store), use the corresponding Redeem APIs (such as `RedeemAppleAppStoreInventoryItems`, `RedeemGooglePlayInventoryItems`, `RedeemSteamInventoryItems`, or `RedeemMicrosoftStoreInventoryItems`). These APIs validate the purchase receipt with the marketplace and grant the items to the player's inventory. For more information, see [Marketplace Redemption](../marketplace/marketplace-redemption/overview.md). +#### Bundles + +When a bundle is purchased (via `PurchaseInventoryItems` or a marketplace Redeem API), the bundle is **automatically unpacked** into the player's inventory. The individual items referenced in the bundle's `ItemReferences` are granted directly — the bundle itself does not appear as an item in the player's inventory. + +For example, purchasing a bundle containing 2x Laser Sword and 2x Laser Gun grants those items individually. The virtual currency cost defined in the bundle's `PriceOptions` is deducted from the player's inventory as part of the transaction. + +Bundles that are linked to marketplace products via `AlternateIds` follow the same unpacking behavior when redeemed. For more information on creating bundles, see [Bundles](../catalog/bundles.md). + ### Transfer Inventory Items The `TransferInventoryItems` API can be used in three different ways. @@ -265,7 +273,7 @@ More information about stacks can be found [here](stacks.md). You can use the `ExecuteInventoryOperations` API to batch multiple inventory operations in a single request. Operations will happen in request order specified and if an operation is unable to be performed, the whole set of operations is canceled. -The `ExecuteInventoryOperations` takes in an `Operation` parameter that is a list of operations. There can be at most ten operations in the `Operation` list but operation types can repeat (for example, 10 Add operations are valid). There is also a limit to 250 items that can be modified/added in a single request. For example, adding a bundle with 50 items counts as 50 items modified. The valid operation types are: +The `ExecuteInventoryOperations` takes in an `Operation` parameter that is a list of operations. There can be at most **50 operations** in the `Operation` list but operation types can repeat (for example, 10 Add operations are valid). There is also a limit to **300 items** that can be modified/added in a single request. For example, adding a bundle with 50 items counts as 50 items modified. The valid operation types are: * Add * Subtract @@ -337,40 +345,9 @@ For example, the following `PurchaseItem` API request can be called multiple tim > [!NOTE] > Using the same `IdempotencyId` for different request types will cause a conflict and throw an error. -### ETags and Conditional Operations - -Inventory operations support ETags for optimistic concurrency control. When you retrieve a player's inventory using `GetInventoryItems`, the response includes an `ETag` value that represents the current state of the inventory collection. - -You can use this `ETag` value in subsequent write operations (such as `AddInventoryItems`, `SubtractInventoryItems`, `UpdateInventoryItems`, `DeleteInventoryItems`, `PurchaseInventoryItems`, `TransferInventoryItems`, and `ExecuteInventoryOperations`) to ensure the inventory hasn't been modified since you last read it. If the inventory has changed since the `ETag` was retrieved, the operation fails with a conflict error, preventing concurrent modifications from silently overwriting each other. +### ETags and Concurrency Control -ETags are passed via HTTP headers on the request: - -- **`X-PlayFab-Economy-If-Match`** - The operation only succeeds if the current inventory ETag matches the provided value. Use this to ensure you're modifying the expected state. -- **`X-PlayFab-Economy-If-None-Match`** - The operation only succeeds if the current inventory ETag does **not** match the provided value. Use this to prevent overwriting a known state. - -This is useful in scenarios where multiple systems or game clients may be modifying the same player's inventory simultaneously, and you need to ensure that operations are applied to the expected state. - -An example `SubtractInventoryItems` request with an ETag header: - -```http -POST /Inventory/SubtractInventoryItems -Content-Type: application/json -X-PlayFab-Economy-If-Match: "1a2b3c4d-5e6f-7890-abcd-ef1234567890" - -{ - "Entity": { - "Type": "title_player_account", - "Id": "ABCD12345678" - }, - "Item": { - "Id": "0b440353-bdbc-48d8-8873-f0988c1f9d8b", - }, - "Amount": 5 -} -``` - -> [!NOTE] -> If the ETag provided in `X-PlayFab-Economy-If-Match` does not match the current state of the inventory, the API returns a conflict error. You should retrieve the latest inventory state and retry the operation with the updated ETag. +Inventory write APIs support optimistic concurrency control through ETags and HTTP headers. For full details, see [Inventory ETags](etags.md). ### Display Properties diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/stacks.md b/playfab-docs/economy-monetization/economy-v2/inventory/stacks.md index 07b265cf8..c4a53c535 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/stacks.md +++ b/playfab-docs/economy-monetization/economy-v2/inventory/stacks.md @@ -120,7 +120,7 @@ When you make purchases with stacks, there are a few parameters that are relevan - For the `Item` object, you can define an optional `StackId` that represents the stack the receiving items will be placed in - There's a`DeleteEmptyStacks` boolean that can be set which deletes the stack if the subtracted amount results in the stack having an amount of 0. -For more information about the `PurchaseInventoryItems` API, see the [Inventory APIs documentation](index.md#purchase-inventory-items). +> For more details on purchasing items, see [PurchaseInventoryItems](/rest/api/playfab/economy/inventory/purchase-inventory-items). An example `PurchaseInventoryItems` request with stacks: diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/toc.yml b/playfab-docs/economy-monetization/economy-v2/inventory/toc.yml index 4e80f15e5..c270be990 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/toc.yml +++ b/playfab-docs/economy-monetization/economy-v2/inventory/toc.yml @@ -11,5 +11,7 @@ items: href: stacks.md - name: Transaction History href: transaction-history.md +- name: ETags + href: etags.md - name: TurboLoading href: turboloading.md diff --git a/playfab-docs/economy-monetization/economy-v2/overview.md b/playfab-docs/economy-monetization/economy-v2/overview.md index 153520dde..893d730c0 100644 --- a/playfab-docs/economy-monetization/economy-v2/overview.md +++ b/playfab-docs/economy-monetization/economy-v2/overview.md @@ -63,3 +63,9 @@ Economy v2 brings new useful features: * [Quickstart](quickstart.md) * [Settings](settings.md) * [Stores](catalog/stores.md) +* [Inventory](inventory/index.md) +* [Marketplace Integrations](marketplace/marketplace-integrations/overview.md) +* [Fraud Prevention](fraud-prevention/index.md) +* [TurboLoading](inventory/turboloading.md) +* [Limits](limits.md) +* [FAQ](faq.md) From 877178080590da8bd45be377861d300773936846 Mon Sep 17 00:00:00 2001 From: edigonzales-microsoft Date: Fri, 20 Feb 2026 11:11:46 -0800 Subject: [PATCH 55/76] Update allowed filename matches in config (#2829) Update allowed filename matches in config --- .acrolinx-config.edn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.acrolinx-config.edn b/.acrolinx-config.edn index fd2404316..7ca95fa35 100644 --- a/.acrolinx-config.edn +++ b/.acrolinx-config.edn @@ -1,5 +1,5 @@ {:allowed-branchname-matches ["main"] - :allowed-filename-matches ["playfab-docs/features" "playfab-docs/data-analytics" "playfab-docs/playstream" "playfab-docs/gamemanager" "playfab-docs/miscellaneous" "playfab-docs/release-notes" "playfab-docs/resources" "playfab-docs/sdks"] + :allowed-filename-matches ["playfab-docs/data-analytics" "playfab-docs/demo-game" "playfab-docs/economy-monetization" "playfab-docs/get-started" "playfab-docs/identity" "playfab-docs/includes" "playfab-docs/live-service-management" "playfab-docs/media" "playfab-docs/miscellaneous" "playfab-docs/multiplayer" "playfab-docs/player-progression" "playfab-docs/pricing" "playfab-docs/release-notes" "playfab-docs/resources" "playfab-docs/sdks" "playfab-docs/test-documents" "playfab-docs/whats-new"] :targets { From e6e3226bb34071b787652bb830ce991c73fa365d Mon Sep 17 00:00:00 2001 From: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:41:35 -0600 Subject: [PATCH 56/76] Cleans up URLs (#2813) * Cleans up URLs, removes language codes, and all login steps point to developer.playfab.com * pf-review-edits-pr-2813-02-23-2026-01 * pf-review-edits-pr-2813-02-23-2026-02 * pf-review-edits-pr-2813-02-23-2026-03 * pf-review-edits-pr-2813-02-23-2026-04 --------- Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --- .../leaderboards/leaderboards-cloudscript.md | 6 +-- .../leaderboards/quickstart-leaderboards.md | 4 +- .../export-data/data-connection-azure-blob.md | 2 +- .../ht-activate-deactivate-telemetry-keys.md | 6 +-- .../ingest-data/ht-telemetry-keys-delete.md | 4 +- .../ingest-data/telemetry-keys-qs.md | 6 +-- .../churn-prediction-quickstart.md | 2 +- .../learn-data/data-explorer/quickstart.md | 4 +- .../learn-data/reports/daily-email-report.md | 2 +- .../reports/real-time-analytics-tutorial.md | 2 +- .../connecting-python-to-insights.md | 2 +- playfab-docs/demo-game/overview.md | 42 +++++++++---------- .../economy-v2/catalog/catalog-views.md | 2 +- .../economy-v2/tutorials/currencies.md | 2 +- .../authentication/aad-authentication.md | 2 +- .../identity/dev-identity/pfab-account.md | 4 +- .../anonymous-login.md | 2 +- .../apple-open-id.md | 2 +- .../battlenet-login.md | 2 +- .../facebook-html5.md | 2 +- .../facebook-unity.md | 18 ++++---- .../google-html5.md | 24 +++++------ .../twitch-html5.md | 16 +++---- .../platform-specific-authentication/uwp.md | 18 ++++---- .../xbox-live-add-on.md | 2 +- .../game-configuration/entities/quickstart.md | 2 +- .../segmentation/advanced-segmentation.md | 2 +- .../player-custom-properties-qs.md | 4 +- .../gamemanager/quickstart.md | 2 +- .../automation/cloudscript-af/quickstart.md | 2 +- .../lobby/lobby-getting-started.md | 2 +- .../multiplayer-unity-plugin-quickstart.md | 2 +- .../matchmaking/quickstart-client-sdk.md | 2 +- .../android-specific-requirements.md | 2 +- .../networking/apple-specific-requirements.md | 2 +- .../party-tutorial-requestpartyservice.md | 2 +- .../party-unity-plugin-quickstart.md | 2 +- .../multiplayer/networking/quickstart.md | 2 +- .../multiplayer/servers/build-definition.md | 10 ++--- .../servers/deploy-using-powershell-api.md | 2 +- .../enable-playfab-multiplayer-servers.md | 10 ++--- ...-for-multiplayer-servers-api-powershell.md | 2 +- ...rt-for-multiplayer-servers-game-manager.md | 2 +- .../using-playfab-servers-to-host-games.md | 2 +- .../servers/windows-runner-sample.md | 18 ++++---- .../player-data/getting-player-profiles.md | 4 +- .../player-data/quickstart.md | 2 +- .../using-player-publisher-data.md | 2 +- .../statistics/quickstart-statistics.md | 4 +- playfab-docs/pricing/support.md | 22 +++++----- playfab-docs/pricing/title-launches.md | 2 +- playfab-docs/sdks/c-sharp/quickstart.md | 2 +- playfab-docs/sdks/cocos2d-x/quickstart.md | 36 ++++++++-------- playfab-docs/sdks/java/quickstart.md | 14 +++---- playfab-docs/sdks/javascript/quickstart.md | 24 +++++------ playfab-docs/sdks/lua/quickstart-corona.md | 14 +++---- playfab-docs/sdks/lua/quickstart-defold.md | 30 ++++++------- playfab-docs/sdks/nodejs/quickstart.md | 18 ++++---- .../sdks/playfab-cpp/quickstart-linux.md | 2 +- .../sdks/playfab-cpp/quickstart-windows.md | 2 +- playfab-docs/sdks/python/quickstart.md | 12 +++--- playfab-docs/sdks/sdkgenerator/quickstart.md | 18 ++++---- .../sdks/unity3d/installing-unity3d-sdk.md | 2 +- playfab-docs/sdks/unity3d/quickstart.md | 2 +- playfab-docs/sdks/unreal/quickstart.md | 2 +- 65 files changed, 233 insertions(+), 233 deletions(-) diff --git a/playfab-docs/community/leaderboards/leaderboards-cloudscript.md b/playfab-docs/community/leaderboards/leaderboards-cloudscript.md index a6afa3237..ed552009a 100644 --- a/playfab-docs/community/leaderboards/leaderboards-cloudscript.md +++ b/playfab-docs/community/leaderboards/leaderboards-cloudscript.md @@ -1,5 +1,5 @@ --- -title: Leaderboards Using Azure Functions +title: Leaderboards using Azure Functions author: braulioal description: Learn how to create and manage leaderboards using Azure Functions in PlayFab. ms.author: braulioal @@ -10,7 +10,7 @@ keywords: playfab, multiplayer, leaderboard, stats ms.localizationpriority: medium --- -# Leaderboards Using Azure Functions +# Leaderboards using Azure Functions In this tutorial, you'll learn how to implement leaderboards using Cloudscript, specifically through [Azure Functions](../../live-service-management/service-gateway/automation/cloudscript-af/index.md). This approach is particularly powerful because it enables you to create custom server-side logic without requiring client updates. @@ -19,7 +19,7 @@ By defining leaderboard-related logic within an Azure Function, your client can ## Prerequisites To follow this tutorial you need to have: -- An Azure PlayFab account, if you don't have one you can create it [here](https://playfab.com/). +- A PlayFab account, if you don't have one you can create it [here](https://developer.playfab.com/). - An Azure subscription, if you don't have one you can create it [here](https://azure.microsoft.com/free/). For more details on how to create an Azure Function check this guide. [Create your first function in Azure using Visual Studio](https://learn.microsoft.com/azure/azure-functions/functions-create-your-first-function-visual-studio) diff --git a/playfab-docs/community/leaderboards/quickstart-leaderboards.md b/playfab-docs/community/leaderboards/quickstart-leaderboards.md index 9c8130bde..30a165b78 100644 --- a/playfab-docs/community/leaderboards/quickstart-leaderboards.md +++ b/playfab-docs/community/leaderboards/quickstart-leaderboards.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Quickstart leaderboards In this guide, we're going to see how to set up the development environment for the Leaderboard service. We're also going -to learn how to create a quick leaderboard from our website [Game Manager](https://developer.playfab.com/en-US/login). +to learn how to create a quick leaderboard from our website [Game Manager](https://developer.playfab.com). ## Prerequisites @@ -59,7 +59,7 @@ PlayFabSettings.staticSettings.DeveloperSecretKey = ""; // Change this to your t ## Creating a title and getting the secret key -- Log in to https://playfab.com/ +- Log in to https://developer.playfab.com/ - Create a title - Find the Title ID in the API Features section under settings. - Generate secret key: diff --git a/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md b/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md index 74233d2cf..e50aff8f9 100644 --- a/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md +++ b/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium First, you need an Azure subscription and a storage account. -For existing PlayFab and Azure customers, you can create a storage container on the [Azure portal](https://ms.portal.azure.com/#allservices) and get started with Data Connections on [Azure PlayFab](https://developer.playfab.com/en-US/sign-up). +For existing PlayFab and Azure customers, you can create a storage container on the [Azure portal](https://ms.portal.azure.com/#allservices) and get started with Data Connections on [Azure PlayFab](https://developer.playfab.com). For existing PlayFab who are new to Azure, you can sign up for an [Azure subscription](https://ms.portal.azure.com/). diff --git a/playfab-docs/data-analytics/ingest-data/ht-activate-deactivate-telemetry-keys.md b/playfab-docs/data-analytics/ingest-data/ht-activate-deactivate-telemetry-keys.md index c1ee81760..0d0f52f2f 100644 --- a/playfab-docs/data-analytics/ingest-data/ht-activate-deactivate-telemetry-keys.md +++ b/playfab-docs/data-analytics/ingest-data/ht-activate-deactivate-telemetry-keys.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # How to activate or deactivate Telemetry Keys in Game Manager -- Sign in to [Game Manager](https://developer.playfab.com/en-US/login). +- Sign in to [Game Manager](https://developer.playfab.com). - Go to **My Studios and Titles** page and select your game title to display the dashboard. - Select **Data** from the menu on the left. - Select the **Telemetry Keys** tab. @@ -25,11 +25,11 @@ To **deactivate** a Telemetry Key: - Expand the **three-dot menu** at the top right corner of the Telemetry Key. - Select the **Deactivate** action. - Select the **Deactivate** button to confirm. -- Once the Telemetry Key has been deactivated you will notice the status will change to Deactivated. +- Once the Telemetry Key has been deactivated you'll notice the status changes to Deactivated. To **activate** a Telemetry Key: - Expand the **three-dot** menu at the top right corner of the Telemetry Key. - Select the **Activate** action. - Select the **Activate** button to confirm. -The status will change to **Active**. +The status changes to **Active**. diff --git a/playfab-docs/data-analytics/ingest-data/ht-telemetry-keys-delete.md b/playfab-docs/data-analytics/ingest-data/ht-telemetry-keys-delete.md index b1feea986..5871318e3 100644 --- a/playfab-docs/data-analytics/ingest-data/ht-telemetry-keys-delete.md +++ b/playfab-docs/data-analytics/ingest-data/ht-telemetry-keys-delete.md @@ -13,9 +13,9 @@ ms.localizationpriority: medium # How to delete Telemetry Keys in Game Manager > [!WARNING] -> Deleting a Telemetry Key is not reversible. Please be aware that even if you create another key with the same name, the new key will be different from the original one that was deleted. +> Deleting a Telemetry Key isn't reversible. Even if you create another key with the same name, the new key will be different from the original one that was deleted. -- Sign in to [Game Manager](https://developer.playfab.com/en-US/login). +- Sign in to [Game Manager](https://developer.playfab.com). - Go to **My Studios and Titles** page and select your game title to display the dashboard. - Select **Data** from the menu on the left. - Select the **Telemetry Keys** tab. diff --git a/playfab-docs/data-analytics/ingest-data/telemetry-keys-qs.md b/playfab-docs/data-analytics/ingest-data/telemetry-keys-qs.md index eb607c467..ac19e3e60 100644 --- a/playfab-docs/data-analytics/ingest-data/telemetry-keys-qs.md +++ b/playfab-docs/data-analytics/ingest-data/telemetry-keys-qs.md @@ -14,7 +14,7 @@ ms.localizationpriority: medium ## Creating Telemetry Keys in Game Manager -- Sign in to [Game Manager](https://developer.playfab.com/en-US/login). +- Sign in to [Game Manager](https://developer.playfab.com). - Go to **My Studios and Titles** page and select your game title to display the dashboard. - Select **Data** from the menu on the left. - Select the **Telemetry Keys** tab. @@ -22,8 +22,8 @@ ms.localizationpriority: medium - Fill the **Key** field. - Select **Create telemetry key**. -Here is an example of how the newly created Telemetry Key should look like: +Here's an example of how the newly created Telemetry Key should look like: ![New telemetry key](media/new-telemetry-key.png) -Once the Telemetry Key has been created, you can use it from your game client when calling [WriteTelemetryEvents API](/rest/api/playfab/events/play-stream-events/write-telemetry-events) by including it via HTTP header X-TelemetryKey as called out in the Overview page. You can look at an example here: [Telemetry Keys Overview](telemetry-keys-overview.md) in the Section **Specifying Entities for Events**s \ No newline at end of file +Once the Telemetry Key has been created, you can use it from your game client when calling [WriteTelemetryEvents API](/rest/api/playfab/events/play-stream-events/write-telemetry-events) by including it via HTTP header X-TelemetryKey as called out in the Overview page. You can look at an example here: [Telemetry Keys Overview](telemetry-keys-overview.md) in the Section **Specifying Entities for Events**. \ No newline at end of file diff --git a/playfab-docs/data-analytics/learn-data/churn-prediction/churn-prediction-quickstart.md b/playfab-docs/data-analytics/learn-data/churn-prediction/churn-prediction-quickstart.md index 231a1aae2..4970ec68c 100644 --- a/playfab-docs/data-analytics/learn-data/churn-prediction/churn-prediction-quickstart.md +++ b/playfab-docs/data-analytics/learn-data/churn-prediction/churn-prediction-quickstart.md @@ -14,7 +14,7 @@ ms.localizationpriority: medium ## Prerequisites -1. Sign in to [PlayFab portal](https://playfab.com). +1. Sign in to [PlayFab portal](https://developer.playfab.com). 2. Navigate to your title. ## Create a Churn Prediction segment and apply mitigation strategy diff --git a/playfab-docs/data-analytics/learn-data/data-explorer/quickstart.md b/playfab-docs/data-analytics/learn-data/data-explorer/quickstart.md index 0be0d56a3..083331cba 100644 --- a/playfab-docs/data-analytics/learn-data/data-explorer/quickstart.md +++ b/playfab-docs/data-analytics/learn-data/data-explorer/quickstart.md @@ -19,7 +19,7 @@ ms.localizationpriority: medium To query the data in basic mode: -1. Log in to the [PlayFab Game Manager](https://developer.playfab.com/en-us/login). +1. Log in to the [PlayFab Game Manager](https://developer.playfab.com). 2. Select your Title. 3. In the left navigation column, select **Data**. 4. Select the **Data Explorer (basic)** tab at the top of the page. @@ -30,7 +30,7 @@ To learn how to author custom Basic queries, see the [Getting Started with Data To query the data in advanced mode -1. Log in to the [PlayFab Game Manager](https://developer.playfab.com/en-us/login). +1. Log in to the [PlayFab Game Manager](https://developer.playfab.com). 2. Select your Title. 3. In the left navigation column, select **Data**. 4. Select the **Data Explorer (advanced)** tab at the top of the page. diff --git a/playfab-docs/data-analytics/learn-data/reports/daily-email-report.md b/playfab-docs/data-analytics/learn-data/reports/daily-email-report.md index f4d693597..3a79abaab 100644 --- a/playfab-docs/data-analytics/learn-data/reports/daily-email-report.md +++ b/playfab-docs/data-analytics/learn-data/reports/daily-email-report.md @@ -25,7 +25,7 @@ Titles are subscribed to the email by default but you'll only receive the email To unsubscribe from this list follow these steps: -- Sign in to [Game Manager](https://developer.playfab.com/en-US/login). +- Sign in to [Game Manager](https://developer.playfab.com). - Go to **My Studios and Titles** page and select your game title to display the dashboard. - Select the **Settings** icon next to the Title name on the upper left side. - Select **Title Settings** tab. diff --git a/playfab-docs/data-analytics/learn-data/reports/real-time-analytics-tutorial.md b/playfab-docs/data-analytics/learn-data/reports/real-time-analytics-tutorial.md index ca9c09d99..9d6120363 100644 --- a/playfab-docs/data-analytics/learn-data/reports/real-time-analytics-tutorial.md +++ b/playfab-docs/data-analytics/learn-data/reports/real-time-analytics-tutorial.md @@ -19,7 +19,7 @@ This tutorial explains end-to-end steps on how to integrate **PlayFab** and **Fa ### Prerequisites * To successfully complete this tutorial, you need a Microsoft Fabric-enabled [capacity](/fabric/enterprise/licenses#capacity). For a limited time, you can [sign up for the Microsoft Fabric (Preview) trial](/fabric/get-started/fabric-trial). -* A PlayFab developer account. Sign up at [playfab.com](https://developer.playfab.com/en-US/sign-up) +* A PlayFab developer account. Sign up at [playfab.com](https://developer.playfab.com) * Microsoft PowerBI Desktop installed. See [Get started with Power BI Desktop](/power-bi/fundamentals/desktop-getting-started#install-and-run-power-bi-desktop) ## Create a Fabric workspace diff --git a/playfab-docs/data-analytics/legacy/connectivity/connecting-python-to-insights.md b/playfab-docs/data-analytics/legacy/connectivity/connecting-python-to-insights.md index 45187ddff..18904a8d4 100644 --- a/playfab-docs/data-analytics/legacy/connectivity/connecting-python-to-insights.md +++ b/playfab-docs/data-analytics/legacy/connectivity/connecting-python-to-insights.md @@ -25,7 +25,7 @@ You need a PlayFab account or user for which the authentication provider is set To verify that the account, or user, is set to use the Microsoft authentication provider: -* Visit the PlayFab [log in page](https://developer.playfab.com/en-us/login). +* Visit the PlayFab [log in page](https://developer.playfab.com). * Select **Sign in with Microsoft** to access your PlayFab account. If you can sign in, then the account is set to use the Microsoft authentication provider. diff --git a/playfab-docs/demo-game/overview.md b/playfab-docs/demo-game/overview.md index 566b46339..42b3d03c1 100644 --- a/playfab-docs/demo-game/overview.md +++ b/playfab-docs/demo-game/overview.md @@ -12,9 +12,9 @@ ms.localizationpriority: medium # Demo game: Winter Starfall -Winter Starfall is a game developed by PlayFab to showcase our different features and provide a way to explore how they are implemented in a live game. +Winter Starfall is a game developed by PlayFab to showcase our different features and provide a way to explore how they're implemented in a live game. -The game is available to play at [WinterStarfall.com](https://winterstarfall.com/). If you already have a PlayFab developer account you can also access it through the developer portal on the My Studios and Titles page. +The game is available to play at [WinterStarfall.com](https://winterstarfall.com/). If you already have a PlayFab developer account, you can also access it through the developer portal on the My Studios and Titles page. ![game manager homepage showing demo games](media/demo-games-overview.png) @@ -27,16 +27,16 @@ The game is built as a web app and uses APIs from the PlayFab SDK along with Pla ## Additional demo features -Winter Starfall comes with features that make it easier to see what is going on 'under the hood' with PlayFab. The game is available for anyone to play, but to get the full use of these features you'll need to sign up for a [free developer account](https://developer.playfab.com/en-us/sign-up). +Winter Starfall comes with features that make it easier to see what is going on 'under the hood' with PlayFab. The game is available for anyone to play, but to get the full use of these features you need to sign up for a [free developer account](https://developer.playfab.com). -Next to the profile icon in the upper right there is a PlayFab icon that will open the PlayFab activity sidebar when clicked. +Next to the profile icon in the upper right there's a PlayFab icon that opens the PlayFab activity sidebar when selected. ![winter-starfall-profile](media/winter-starfall-activity.png) -1. The activity sidebar shows a list of API calls that updates as you play the game. Each API call is tagged and color coded to indicate which PlayFab SDK it is related to. +1. The activity sidebar shows a list of API calls that updates as you play the game. Each API call is tagged and color coded to indicate which PlayFab SDK it's related to. 1. You can select one of the API calls in the list to view the full API request and response. -1. Selecting **View title F8941** will open the title in Game Manager where you can see how the different features are configured. This is where you'll be prompted to sign in with a PlayFab developer account. -1. **Clear** will remove all the current notifications from the activity bar. +1. Selecting **View title F8941** opens the title in Game Manager where you can see how the different features are configured. This step is where you're prompted to sign in with a PlayFab developer account. +1. **Clear** removes all the current notifications from the activity bar. > [!NOTE] -> You can play the demo game at any time, but to access Game Manager you'll need to sign up for a [free developer account](https://developer.playfab.com/en-us/sign-up). +> You can play the demo game at any time, but to access Game Manager you need to sign up for a [free developer account](https://developer.playfab.com). ## Included PlayFab features @@ -53,13 +53,13 @@ The following section breaks down in more detail the different PlayFab features ### Authentication -The first thing that happens in any PlayFab game is logging in a player, which returns an authentication token that is required for all subsequent API calls. Winter Starfall supports multiple forms of recoverable login with email, Microsoft (via OpenID), Google, and Facebook. The [source code and scenarios tutorial](source-code-and-best-practices.md) gives an in depth walkthrough of the login flow and best practices for player authentication. +The first thing that happens in any PlayFab game is logging in a player, which returns an authentication token that is required for all subsequent API calls. Winter Starfall supports multiple forms of recoverable sign-in with email, Microsoft (via OpenID), Google, and Facebook. The [source code and scenarios tutorial](source-code-and-best-practices.md) gives an in-depth walkthrough of the sign in flow and best practices for player authentication. [Learn more about PlayFab Authentication](../identity/player-identity/authentication/index.md) ### Economy -As a fantasy RPG style game, Winter Starfall includes an economy system for the player to visit stores, purchase items, and earn currency through battles. PlayFab's newest economy service handles everything related to inventory and commerce in the game. The [source code and scenarios tutorial](source-code-and-best-practices.md) gives an in depth walkthrough of the purchase flow that occurs in the game. +As a fantasy role-playing game (RPG), Winter Starfall includes an economy system for the player to visit stores, purchase items, and earn currency through battles. PlayFab's newest economy service handles everything related to inventory and commerce in the game. The [source code and scenarios tutorial](source-code-and-best-practices.md) gives an in depth walkthrough of the purchase flow that occurs in the game. [Learn more about Economy V2](../economy-monetization/economy-v2/overview.md) @@ -67,11 +67,11 @@ As a fantasy RPG style game, Winter Starfall includes an economy system for the Players in PlayFab have associated data that is stored in the service by different features. Player data as a feature allows you to store player-related information in key/value pairs or objects and files that can be shared across multiple games and devices. -In Winter Starfall, Player data is used to store the game state and information like which characters have joined the player's party. When the player moves through the story, their position is recorded in their player profile through a call to the [UpdateUserData](xref:titleid.playfabapi.com.client.playerdatamanagement.updateuserdata) API. This data is then accessed with GetUserData when they log in, to load the player into the right point in the story with all their past progress. +In Winter Starfall, player data is used to store the game state and information like which characters joined the player's party. When the player moves through the story, their position is recorded in their player profile through a call to the [UpdateUserData](xref:titleid.playfabapi.com.client.playerdatamanagement.updateuserdata) API. This data is then accessed with `GetUserData` when they sign in, to load the player into the right point in the story with all their past progress. ![winter-starfall-player-data](media/winterstarfall-player-data.jpg) -For example, these are the API request and response body from the call to `GetUserData` during the login flow. +For example, these examples are the API request and response body from the call to `GetUserData` during the login flow. **GetUserData - Request** @@ -116,7 +116,7 @@ For example, these are the API request and response body from the call to `GetUs ### Title data -Title data is similar to Player data in that it stores key-value pairs, only the data pertains to the game title instead of a specific player. Winter Starfall uses title data in conjuction with the Economy system to calculate the price when selling an item by storing the value `multipliers` with a value of `sell, 0.5`. For more information on how the sale flow works, see the [source code and scenarios tutorial](source-code-and-best-practices.md). +Title data is similar to Player data in that it stores key-value pairs, only the data pertains to the game title instead of a specific player. Winter Starfall uses title data with the Economy system to calculate the price when selling an item by storing the value `multipliers` with a value of `sell, 0.5`. For more information on how the sale flow works, see the [source code and scenarios tutorial](source-code-and-best-practices.md). ![winterstarfall title data overview in game manager](media/winterstarfall-title-data.jpg) @@ -124,15 +124,15 @@ Title data is similar to Player data in that it stores key-value pairs, only the ### CloudScript with Azure Functions -CloudScript is a very flexible feature that allows you to implement custom server-side fucntionality, which allows for nearly limitless solutions when paired with other PlayFab features. +CloudScript is a flexible feature that allows you to implement custom server-side functionality, which allows for nearly limitless solutions when paired with other PlayFab features. -The game uses this feature to solve for a number of scenarios: +The game uses this feature to solve for many scenarios: - [CombatVictory](https://github.com/PlayFab/winter-starfall/blob/main/azure-functions/CombatVictory.cs) - After the player wins a battle, execute a series of actions to grant exp, items, and add party members. - [PlayerCreated](https://github.com/PlayFab/winter-starfall/blob/main/azure-functions/PlayerCreated.cs) - Equips a new player with starting items and stats. - [ProgressCheckpoint](https://github.com/PlayFab/winter-starfall/blob/main/azure-functions/ProgressCheckpoint.cs) - Performs actions to unlock items and characters after reaching key story points. - [ResetPlayer](https://github.com/PlayFab/winter-starfall/blob/main/azure-functions/ResetPlayer.cs) - Wipes user data, items, and statistics for a full reset. -- [SellItem](https://github.com/PlayFab/winter-starfall/blob/main/azure-functions/SellItem.cs) - Enables selling items at a discount, which is not an inherent feature of the economy system. The purchase/sale flow is covered in more detail in the [source code and scenarios tutorial](source-code-and-best-practices.md). +- [SellItem](https://github.com/PlayFab/winter-starfall/blob/main/azure-functions/SellItem.cs) - Enables selling items at a discount, which isn't an inherent feature of the economy system. The purchase/sale flow is covered in more detail in the [source code and scenarios tutorial](source-code-and-best-practices.md). [Learn more about CloudScript with Azure Functions](../live-service-management/service-gateway/automation/cloudscript-af/index.md) @@ -152,20 +152,20 @@ In addition to title news, PlayFab offers other communication features like temp ## Demo limitations -Because Winter Starfall is powered by real player data, some features are limited in scope in the Game Manager view. This section will give an overview of what the limited features would look like in Game Manager. To explore these pages in more detail, you can [download the source code](https://github.com/PlayFab/winter-starfall) and run a local instance of the game, or create your own new title from scratch. +Because Winter Starfall is powered by real player data, some features are limited in scope in the Game Manager view. This section gives an overview of what the limited features would look like in Game Manager. To explore these pages in more detail, you can [download the source code](https://github.com/PlayFab/winter-starfall) and run a local instance of the game, or create your own new title from scratch. > [!NOTE] > For a full guide to the features in the developer portal, see the [Game Manager documentation](../live-service-management/gamemanager/index.md) ### Players -The **Players** section of Game Manager is hidden in the Winter Starfall title in order to protect player information. Usually, you would be able to query the entire list of players in your game and select an individual account to update their data through Game Manager. From the player overview page you can view all information related to the player including inventory items, a record of all logins, player data, and more. +The **Players** section of Game Manager is hidden in the Winter Starfall title in order to protect player information. Usually, you would be able to query the entire list of players in your game and select an individual account to update their data through Game Manager. From the player overview page, you can view all information related to the player including inventory items, a record of all logins, player data, and more. ![player overview](media/player-overview.png) ### Data & Analytics -Some of the features under the **Analyze** section are also limited to protect title and player information. This includes the **Data** and **Audit History** sections. The **Data** section contains features like [Data Explorer](../data-analytics/learn-data/data-explorer/index.md) which allows you to query and view a PlayFab event records, which will show events (API calls) such as when a specific player logged in. +Some of the features under the **Analyze** section are also limited to protect title and player information. This limitation includes the **Data** and **Audit History** sections. The **Data** section contains features like [Data Explorer](../data-analytics/learn-data/data-explorer/index.md), which allows you to query and view a PlayFab event record, which shows events (API calls) such as when a specific player logged in. ![data page](media/demo-game-data.png) @@ -175,13 +175,13 @@ For a full view of what other features are part of the **Data** section, see the ### Other -Under title settings, the **Secret keys** tab is hidden. See the [documention for secret key management](../live-service-management/gamemanager/secret-key-management.md). +Under title settings, the **Secret keys** tab is hidden. See the [documentation for secret key management](../live-service-management/gamemanager/secret-key-management.md). ![Game Manager UI showing Secret Keys page](media/secret-keys.jpg) ## Next steps -After trying the demo, we recommend starting with these topics to learn more about how PlayFab works: +After trying the demo, we recommend starting with these articles to learn more about how PlayFab works: - Learn more about [Game Manager](../live-service-management/gamemanager/index.md) - Learn about the [Entity model](../live-service-management/game-configuration/entities/index.md) - Learn about [PlayFab Services SDK](../sdks/sdk-overview.md) diff --git a/playfab-docs/economy-monetization/economy-v2/catalog/catalog-views.md b/playfab-docs/economy-monetization/economy-v2/catalog/catalog-views.md index 72ddf328b..3f5bec874 100644 --- a/playfab-docs/economy-monetization/economy-v2/catalog/catalog-views.md +++ b/playfab-docs/economy-monetization/economy-v2/catalog/catalog-views.md @@ -80,7 +80,7 @@ Catalog Views is a regularly updated storage blob of query results, accessible t ### Prerequisites 1. Catalog Views is currently in Private Preview. Send an email to **PFEconomyPreviews@microsoft.com** with the subject **Access to Catalog Views Private Preview** along with your PlayFab Title ID to be able to start using the feature in your environment. -2. Sign in to [PlayFab portal](https://playfab.com). +2. Sign in to [PlayFab portal](https://developer.playfab.com). 3. Navigate to your title. ### Create a New View diff --git a/playfab-docs/economy-monetization/economy-v2/tutorials/currencies.md b/playfab-docs/economy-monetization/economy-v2/tutorials/currencies.md index 1b9450187..52b78ef4c 100644 --- a/playfab-docs/economy-monetization/economy-v2/tutorials/currencies.md +++ b/playfab-docs/economy-monetization/economy-v2/tutorials/currencies.md @@ -18,7 +18,7 @@ Get started with PlayFab Economy by using the [PlayFab Services SDK](../../../sd ## Prerequisites -* A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up) +* A [PlayFab developer account](https://developer.playfab.com) * The PlayFab Beta SDK (You can find more information on the [Postman Quickstart](../../../sdks/postman/postman-quickstart.md#adding-playfab-collections)) ## Get a title entity token diff --git a/playfab-docs/identity/dev-identity/authentication/aad-authentication.md b/playfab-docs/identity/dev-identity/authentication/aad-authentication.md index b3c48de48..7cacb2c89 100644 --- a/playfab-docs/identity/dev-identity/authentication/aad-authentication.md +++ b/playfab-docs/identity/dev-identity/authentication/aad-authentication.md @@ -20,7 +20,7 @@ PlayFab supports two methods for user authentication. The first is the original You can create a new PlayFab account using an existing or new Microsoft Account. The PlayFab authentication system is no longer available for new accounts. -1. Navigate to [PlayFab's Signup page](https://developer.playfab.com/en-US/sign-up). +1. Navigate to [PlayFab's Signup page](https://developer.playfab.com). 2. Select **Sign up with Microsoft** and follow the signup flow. ![Sign up with Microsoft](media/aad-sign-up.png) diff --git a/playfab-docs/identity/dev-identity/pfab-account.md b/playfab-docs/identity/dev-identity/pfab-account.md index cbd2bd07c..6e8d2ee11 100644 --- a/playfab-docs/identity/dev-identity/pfab-account.md +++ b/playfab-docs/identity/dev-identity/pfab-account.md @@ -12,11 +12,11 @@ ms.localizationpriority: medium # Creating a PlayFab account -Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). If you already have a PlayFab account, you can skip this step. +Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com). If you already have a PlayFab account, you can skip this step. ![PlayFab - Create your account](media/playfab-create-new-account.png) -Once you have a PlayFab account, navigate to the PlayFab home page, [https://playfab.com](https://playfab.com), and sign in. +Once you have a PlayFab account, navigate to the PlayFab home page, [https://developer.playfab.com](https://developer.playfab.com), and sign in. Since PlayFab doesn't know the name of your game studio or the title of your game, when you create a studio, a placeholder title called **My Game** is created for you. You can edit your title's information in the **Create Title** screen at any time. diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md b/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md index c37b96687..7d5b168c7 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md @@ -33,7 +33,7 @@ To enhance the security of anonymous login, PlayFab implemented a crucial securi ## Prerequisites - A unique identifier for the player (CustomID) -- A registered [PlayFab](https://playfab.com/) title +- A registered [PlayFab](https://developer.playfab.com/) title - Your PlayFab title's secret key - Familiarity with [sign-in basics and best practices](../login/login-basics-best-practices.md) - A server with a valid domain name to serve static HTML files diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/apple-open-id.md b/playfab-docs/identity/player-identity/platform-specific-authentication/apple-open-id.md index b8fc609f7..1a29fabe7 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/apple-open-id.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/apple-open-id.md @@ -37,7 +37,7 @@ Save the identifier where you can access it easily. You'll use in the next set o To set up the Apple Add-on in PlayFab: -1. Sign in to [Game Manager](https://developer.playfab.com/en-US/login). +1. Sign in to [Game Manager](https://developer.playfab.com). 2. Select your title from the My Studios and Titles page. 3. In the **Add-ons** pane, select the **Apple** platform. 4. To install the Apple add-on, select **Install Apple**. diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/battlenet-login.md b/playfab-docs/identity/player-identity/platform-specific-authentication/battlenet-login.md index 5fbb39fdb..21f3d5241 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/battlenet-login.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/battlenet-login.md @@ -19,7 +19,7 @@ This tutorial guides you through the process of setting up PlayFab authenticatio You need: - A [Battle.net account](https://developer.battle.net) for testing. -- A Registered [PlayFab](https://playfab.com/) title. +- A Registered [PlayFab](https://developer.playfab.com/) title. - A familiarity with [Login basics and Best Practices](../login/login-basics-best-practices.md). - A server with a valid domain name to act as a static HTML file. Consult the [Running an HTTP server for testing](running-an-http-server-for-testing.md) tutorial for information on how to set one up. diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/facebook-html5.md b/playfab-docs/identity/player-identity/platform-specific-authentication/facebook-html5.md index 7da4b4a92..be29f3036 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/facebook-html5.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/facebook-html5.md @@ -17,7 +17,7 @@ This tutorial is designed to guide you through PlayFab authentication using Face ## Requirements - A [Facebook account](https://www.facebook.com/) for testing. -- A registered [PlayFab](https://playfab.com/) title. +- A registered [PlayFab](https://developer.playfab.com/) title. - A familiarity with [sign-in basics and best practices](../login/login-basics-best-practices.md). - A minimal server, with a valid domain name to serve static HTML file. diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/facebook-unity.md b/playfab-docs/identity/player-identity/platform-specific-authentication/facebook-unity.md index 541bb4115..85625bd3a 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/facebook-unity.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/facebook-unity.md @@ -19,7 +19,7 @@ This tutorial guides you through an example of PlayFab authentication using Face - [Unity 5+](https://unity3d.com/) and a created project. - [Facebook account](https://www.facebook.com/) for testing. - [Facebook SDK](https://developers.facebook.com/docs/unity/) imported into the project. -- Registered [PlayFab](https://playfab.com/) title. +- Registered [PlayFab](https://developer.playfab.com/) title. - [PlayFab SDK](https://aka.ms/playfabunitysdkdownload) imported into the project with a configured title reference. - Familiarity with [Login basics and Best Practices](../login/login-basics-best-practices.md). @@ -45,10 +45,10 @@ A new **Application** pop-up will open. ![Facebook new app ID](media/tutorials/facebook-new-app-id.png) 1. Navigate to the **Settings** tab. -2. Then move to the **Basic** sub-tab. +2. Then move to the **Basic** subtab. 3. Locate your **Application ID**. - Copy it somewhere to a safe place that is easily accessed. -We will use it later to set up the Facebook SDK. +We'll use it later to set up the Facebook SDK. ![Facebook save app ID](media/tutorials/facebook-save-app-id.png) @@ -58,7 +58,7 @@ We will use it later to set up the Facebook SDK. 2. Verify that it has an assigned **User Token**. > [!NOTE] -> If you *do not* have an assigned user token, request one using the button to the right of your screen. Refer to this page whenever you need a fresh user token. If authorization fails during testing on a PC, token expiration may be the most likely reason. Refresh the page to get a new user token and test again. +> If you *don't* have an assigned user token, request one using the button to the right of your screen. Refer to this page whenever you need a fresh user token. If authorization fails during testing on a PC, token expiration might be the most likely reason. Refresh the page to get a new user token and test again. ![Facebook Access Token Tool](media/tutorials/facebook-unity/access-token-tool.png) @@ -203,17 +203,17 @@ public class PlayfabFacebookAuthExample : MonoBehaviour ### Running the application on Android -Before launching the application on Android, you are required to perform additional configuration steps: +Before launching the application on Android, you're required to perform additional configuration steps: - First, you need to ensure you have the Android platform selected, and the unique **Package ID** set (as indicated in the example below. > [!NOTE] -> Please make sure to create your own *unique* **Package ID**. +> Make sure to create your own *unique* **Package ID**. ![Set Android package ID](media/tutorials/facebook-unity/set-android-package-id.png) > [!TIP] -> **Optional step**: Install [Open SSL](https://wiki.openssl.org/index.php/Binaries) and add it to the **PATH** environment variable. If it is missing, Unity will produce a harmless error during the build. This error does *not* stop the build, or effect the execution. +> **Optional step**: Install [Open SSL](https://wiki.openssl.org/index.php/Binaries) and add it to the **PATH** environment variable. If it's missing, Unity will produce a harmless error during the build. This error doesn't* stop the build, or effect the execution. Next, in your **Facebook Application** console: @@ -247,7 +247,7 @@ Before launching the Application on iOS, you have to perform additional configur - First, ensure that you have the **iOS** platform selected. - Then, set a unique **Bundle ID** as indicated in the example provided below. -- Please make sure to create your own *unique* **Package ID**. +- Make sure to create your own *unique* **Package ID**. ![Set iOS bundle ID](media/tutorials/facebook-unity/set-ios-bundle-id.png) @@ -303,4 +303,4 @@ Open your PlayFab title in Game Manager. ![PlayStream Debugger Facebook authentication event](media/tutorials/facebook-unity/playfab-facebook-auth-event.png) -At this point you have successfully integrated Facebook Authentication for PlayFab. +At this point, you have successfully integrated Facebook Authentication for PlayFab. diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/google-html5.md b/playfab-docs/identity/player-identity/platform-specific-authentication/google-html5.md index 873c47c8d..5a3965dd4 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/google-html5.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/google-html5.md @@ -16,18 +16,18 @@ This tutorial guides you through the process of PlayFab authentication using Goo ## Requirements -You will need: +You'll need: - A [Google account](https://google.com/) for testing. -- A Registered `[PlayFab](https://playfab.com/)` title. +- A Registered `[PlayFab](https://developer.playfab.com/)` title. - Familiarity with [Login basics and Best Practices](../login/login-basics-best-practices.md). - At the minimum, a server with a valid domain name to act as a static HTML file. Consult the [Running an HTTP server for testing](running-an-http-server-for-testing.md) tutorial for information on how to set one up. ## Server and domain -This guide requires a server with a valid domain to follow. If you do not have a registered domain and remote web server yet, please follow our [Running an HTTP server for testing](running-an-http-server-for-testing.md) tutorial for information on how to set one to run a local web server with a valid domain name. +This guide requires a server with a valid domain to follow. If you don't have a registered domain and remote web server yet, follow our [Running an HTTP server for testing](running-an-http-server-for-testing.md) tutorial for information on how to set one to run a local web server with a valid domain name. -Throughout this guide, we will assume your domain is `[http://playfab.example](http://playfab.example)`. +Throughout this guide, we'll assume your domain is `[http://playfab.example](http://playfab.example)`. ## Registering a Google API project @@ -44,7 +44,7 @@ Start by navigating to the [Google API Console](https://console.developers.googl ![Google API Manager new project](media/tutorials/google-html5/create-new-project.png) > [!NOTE] -> It is normal for **API Manager** to take 10-20 seconds to generate the project. +> It's normal for **API Manager** to take 10-20 seconds to generate the project. @@ -57,7 +57,7 @@ Once the Project is created: ![Google API Manager OAuth consent screen](media/tutorials/google-html5/oauth-consent-screen.png) 1. Fill out an App Name -2. Make sure there are emails for **user suport email** and **Developer Contact Email** +2. Make sure there are emails for **user support email** and **Developer Contact Email** 3. Then select **SAVE AND CONTINUE** ![Google API Manager OAuth Consent Screen configuration](media/tutorials/google-html5/create-oauth-consent-screen-1.png) @@ -82,7 +82,7 @@ On the **OAuth client** screen shown below, the Google API Manager reveals two i 2. The **client secret**. > [!NOTE] -> Be sure to copy and save these values in a safe place that is easily accessible, as they will be used in the authorization process shown later in this tutorial. +> Be sure to copy and save these values in a safe place that is easily accessible, as they'll be used in the authorization process shown later in this tutorial. ![Google API Manager OAuth client ID and secret](media/tutorials/google-html5/oauth-client-credentials.png) @@ -102,14 +102,14 @@ Go to the PlayFab **Game Manager** page for your title. > [!NOTE] > As of July 2017, **Google API Manager** has a bad habit of *not* hooking the **Allowed JS** origin domain properly. If you receive the following error: > **"idpiframe_initialization_failed", details: "Not a valid origin for the client: somedomain.com..."** -> Please remove the credentials and recreate them. *There is no need to delete the entire project - just the credentials.* +> Remove the credentials and recreate them. *There's no need to delete the entire project - just the credentials.* ## Testing using an access token In this example, we show how to test the LoginWithGoogleAccount API using the classic access token approach. Use the HTML code provided below for your testing. > [!NOTE] -> Please *make sure* to replace `YOUR_CLIENT_ID` and `YOUR_PLAYFAB_TITLE` with your own values. +> Make sure* to replace `YOUR_CLIENT_ID` and `YOUR_PLAYFAB_TITLE` with your own values. > [!Note] > the **AccessToken** param is missing in the **LoginWithGoogleAccountRequest** object in the TypeScript typings files. If you are using TypeScript with the Node SDK, you can create a custom type @@ -183,7 +183,7 @@ In this example, we show how to test the LoginWithGoogleAccount API using the cl Testing using the (deprecated) Google Sign-in Platform library > [!NOTE] -> The sample below uses the Google Sign-In platform library. **According to the [Google Identity public documentation site](https://developers.google.com/identity/gsi/web/guides/migration), the Google Sign-In JavaScript platform library for Web will be deprecated March 31, 2023**. This sample will not work for newly created Google clients moving forward - please refer to the prior code sample, which uses the newer Google Identity Services library! +> The sample below uses the Google Sign-In platform library. **According to the [Google Identity public documentation site](https://developers.google.com/identity/gsi/web/guides/migration), the Google Sign-In JavaScript platform library for Web will be deprecated March 31, 2023**. This sample won't work for newly created Google clients moving forward - refer to the prior code sample, which uses the newer Google Identity Services library! ```html @@ -233,7 +233,7 @@ In this example, we show how to test the LoginWithGoogleAccount API using the cl ``` -Remember to open this page using your web server, and make sure to access this page using the URL you specified, while configuring Google Project, (`[PlayFab](http://playfab.example)` in our case). +Remember to open this page using your web server, and make sure to access this page using the URL you specified, while configuring Google Project, ([PlayFab](http://playfab.example) in our case). 1. Once the page opens, select **G Signed In**, and follow the general Google authentication flow. 2. When this is finished, the script will try to authenticate on the PlayFab side and output the result. @@ -241,4 +241,4 @@ Remember to open this page using your web server, and make sure to access this p ![Google Auth Example](media/tutorials/google-html5/google-auth-example.png) > [!NOTE] -> If you *already have* a Google authentication session running, you will not have to select **G Signed In**. Everything will happen automatically. +> If you *already have* a Google authentication session running, you won't have to select **G Signed In**. Everything will happen automatically. diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/twitch-html5.md b/playfab-docs/identity/player-identity/platform-specific-authentication/twitch-html5.md index 949f82235..4f48d0203 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/twitch-html5.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/twitch-html5.md @@ -19,7 +19,7 @@ This tutorial has been designed to guide you through the process of PlayFab auth Prior to beginning, you should have: - A [Twitch Account](https://www.twitch.tv/) for testing. -- A Registered [PlayFab](https://playfab.com/) title. +- A Registered [PlayFab](https://developer.playfab.com/) title. - Familiarity with [Login basics and Best Practices](../login/login-basics-best-practices.md). - At the minimum, a server with a valid domain name to serve static HTML files. @@ -28,14 +28,14 @@ Prior to beginning, you should have: ## Server and domain -This tutorial requires a web server, in order to follow the instructions. If you do not have a registered remote web server yet, please follow our [Running an HTTP server for testing](running-an-http-server-for-testing.md) tutorial, for information on how to run a local web server. +This tutorial requires a web server, in order to follow the instructions. If you don't have a registered remote web server yet, follow our [Running an HTTP server for testing](running-an-http-server-for-testing.md) tutorial, for information on how to run a local web server. >[!NOTE] -> Throughout this tutorial, we will assume your domain is `[http://localhost/](http://localhost/)`. +> Throughout this tutorial, we'll assume your domain is `[http://localhost/](http://localhost/)`. ## Registering a Twitch application -Start by navigating to the [Twitch website](https://www.twitch.tv/), and verifying that you are logged in. +Start by navigating to the [Twitch website](https://www.twitch.tv/), and verifying that you're logged in. 1. Navigate to the **Account** drop-down. 2. Select **Settings** from the menu provided. @@ -46,7 +46,7 @@ On the **Settings** page, select **Connections (1)**, as shown below. ![Twitch settings connections](media/tutorials/twitch-html5/twitch-settings-connections.png) -At the very bottom of the page, select the **Register your application (1)** button, as shown below. +At the bottom of the page, select the **Register your application (1)** button, as shown below. ![Twitch open application registration page](media/tutorials/twitch-html5/twitch-open-application-registration.png) @@ -65,13 +65,13 @@ A page will open that lets you configure a new app. Once the application is registered, the page will be updated and reveal the Client ID for your application. > [!NOTE] -> Keep this Client ID in a safe and easily accessible place, as you will be using it later to configure your PlayFab title. +> Keep this Client ID in a safe and easily accessible place, as you'll be using it later to configure your PlayFab title. ![Twitch manage application](media/tutorials/twitch-html5/twitch-manage-application.png) ## Configuring a PlayFab title -Once you acquire your Twitch Client ID, you may enable and configure a Twitch Add-on for your PlayFab title. +Once you acquire your Twitch Client ID, you can enable and configure a Twitch Add-on for your PlayFab title. 1. On your **PlayFab Title** screen, go to the menu and select the **Add-ons** item. 2. Then select the **Twitch** icon link. @@ -169,7 +169,7 @@ Make sure to replace `TWITCH_CLIENT_ID_GOES_HERE` and `PLAYFAB_TITLE_ID_GOES_HER 4. Follow any **Twitch** instructions in the pop-up window, and watch the output. > [!IMPORTANT] -> If you *already have* a Twitch auth session going when reaching the page, it is possible for callbacks to fire in a different, unexpected order. This case is shown in the screenshot shown below. However, you should make sure that only **Logging in via PlayFab** follows after **Logged in with Twitch**. This indicates that the token was received or restored from the local storage, and we do not have to wait for the Twitch SDK to start signing in to PlayFab. +> If you *already have* a Twitch auth session going when reaching the page, it's possible for callbacks to fire in a different, unexpected order. This case is shown in the screenshot shown below. However, you should make sure that only **Logging in via PlayFab** follows after **Logged in with Twitch**. This indicates that the token was received or restored from the local storage, and we don't have to wait for the Twitch SDK to start signing in to PlayFab. ![Twitch Auth Example](media/tutorials/twitch-html5/twitch-auth-example.png) diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/uwp.md b/playfab-docs/identity/player-identity/platform-specific-authentication/uwp.md index 74474c8b3..70d9c6045 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/uwp.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/uwp.md @@ -15,16 +15,16 @@ ms.localizationpriority: medium This tutorial guides you through the procedure for PlayFab authentication using the Universal Windows Platform (UWP). > [!IMPORTANT] -> This procedure serves as a very basic introduction on how you can obtain all entities, and commit authentication via Windows Hello and PlayFab. For a more sophisticated example of Windows Hello and PlayFab authentication, consider our `[UWPExample project](https://github.com/PlayFab/UWPExample)`. +> This procedure serves as a basic introduction on how you can obtain all entities, and commit authentication via Windows Hello and PlayFab. For a more sophisticated example of Windows Hello and PlayFab authentication, consider our `[UWPExample project](https://github.com/PlayFab/UWPExample)`. ## Requirements - Follow the [MSDN "Get Set Up" Guide](/windows/apps/windows-app-sdk/set-up-your-development-environment) to prepare Windows and Visual Studio for UWP development. -- Have a registered [PlayFab](https://playfab.com/) title. +- Have a registered [PlayFab](https://developer.playfab.com/) title. - Be familiar with [Login basics and Best Practices](../login/login-basics-best-practices.md). > [!NOTE] -> it is *very* important that you use the Windows 10 operating system, are logged in with a verified Microsoft account, and have configured an access interface such as PIN. If these requirements are *not* met, the app will fail without any useful explanation of why. +> It is *very* important that you use the Windows 10 operating system, are logged in with a verified Microsoft account, and have configured an access interface such as PIN. If these requirements aren't* met, the app will fail without any useful explanation of why. ## Preparing a Visual Studio project @@ -58,7 +58,7 @@ In the **NuGet Manager** window: ![Visual Studio Install PlayFab SDK](media/tutorials/uwp/vs-install-playfab-sdk.png) -Once finished, your basic project setup is complete. In the next section we will modify 2 classes that should be automatically generated on project creation: +Once finished, your basic project setup is complete. In the next section we'll modify two classes that should be automatically generated on project creation: 1. **App** 2. **MainPage** @@ -67,7 +67,7 @@ Once finished, your basic project setup is complete. In the next section we will ### App.xaml.cs -This class will just set up our PlayFab SDK by setting a proper title ID. Do not forget to replace the title ID with your own. +This class will just set up our PlayFab SDK by setting a proper title ID. Don't forget to replace the title ID with your own. ```csharp using System; @@ -171,7 +171,7 @@ namespace GettingStartedPlayfabUWP ### MainPage.xaml -This file contains the layout for our main page. This is a *super trivial* layout with 2 buttons, and a text input combined in a vertically oriented grid. +This file contains the layout for our main page. This is a *super trivial* layout with two buttons, and a text input combined in a vertically oriented grid. The buttons are bound to specific methods, and the textbox is accessible via its name `UsernameInput`. @@ -197,7 +197,7 @@ The buttons are bound to specific methods, and the textbox is accessible via its ### MainPage.xaml.cs -This is the functional class for the main page and it is the heart of the example. Please refer to the code comments, and review the different methods that are designed to walk you through PlayFab+Hello register and login. +This is the functional class for the main page and it's the heart of the example. Refer to the code comments, and review the different methods that are designed to walk you through PlayFab+Hello register and login. The easiest approach to start learning the code is to review the methods that are triggered by the corresponding buttons: @@ -458,7 +458,7 @@ To run the application: Follow the instruction that **Windows** offers for authentication. -1. Once your identity is confirmed, you will see the confirmation message saying that the account was **Registered and signed in**. +1. Once your identity is confirmed, you'll see the confirmation message saying that the account was **Registered and signed in**. 2. With a **Session Ticket**. ![UWP example - register confirmation](media/tutorials/uwp/uwp-example-register-confirmation.png) @@ -469,7 +469,7 @@ Follow the instruction that **Windows** offers for authentication. Follow the instruction that Windows offers for authentication. -1. Once your identity is confirmed, you will see the confirmation message saying that the account is **Signed in**. +1. Once your identity is confirmed, you'll see the confirmation message saying that the account is **Signed in**. 2. With a **Session Ticket**. ![UWP example - sign in confirmation](media/tutorials/uwp/uwp-example-sign-in-confirmation.png) diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md b/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md index 596edabee..b5080f952 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/xbox-live-add-on.md @@ -20,7 +20,7 @@ In this tutorial, you'll learn how to configure token validation by specifying w ## Requirements -- A registered [PlayFab](https://playfab.com/) title. +- A registered [PlayFab](https://developer.playfab.com/) title. - [Partner Center](https://partner.microsoft.com/) account with an Xbox Live enabled title. ## Partner Center Product ID and Xbox Live Title ID diff --git a/playfab-docs/live-service-management/game-configuration/entities/quickstart.md b/playfab-docs/live-service-management/game-configuration/entities/quickstart.md index b90c77b17..2b7111e86 100644 --- a/playfab-docs/live-service-management/game-configuration/entities/quickstart.md +++ b/playfab-docs/live-service-management/game-configuration/entities/quickstart.md @@ -18,7 +18,7 @@ For information on migrating from the legacy account and data systems to PlayFab ## Requirements -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). - An installed copy of the Unity Editor. For information on installing the Unity Editor, see [Installing Unity](https://docs.unity3d.com/Manual/GettingStartedInstallingUnity.html) in the Unity documentation. You can also install a version of the Unity using the Visual Studio feature installer. > [!NOTE] > The PlayFab Unity3D SDK supports Unity Editor version 5.3 and higher. diff --git a/playfab-docs/live-service-management/game-configuration/segmentation/advanced-segmentation.md b/playfab-docs/live-service-management/game-configuration/segmentation/advanced-segmentation.md index 293c18aab..1a6f25367 100644 --- a/playfab-docs/live-service-management/game-configuration/segmentation/advanced-segmentation.md +++ b/playfab-docs/live-service-management/game-configuration/segmentation/advanced-segmentation.md @@ -28,7 +28,7 @@ You can create segments with Player Custom properties either via API or Game man ### Via Game Manager -- Sign in to [Game Manager](https://developer.playfab.com/en-US/login). +- Sign in to [Game Manager](https://developer.playfab.com). - Go to the **Players** page. - Go to the **Segments** tab. - [Create or update a segment](segmentation-quickstart.md). diff --git a/playfab-docs/live-service-management/game-configuration/segmentation/player-custom-properties-qs.md b/playfab-docs/live-service-management/game-configuration/segmentation/player-custom-properties-qs.md index 9d56ad16e..229f3579b 100644 --- a/playfab-docs/live-service-management/game-configuration/segmentation/player-custom-properties-qs.md +++ b/playfab-docs/live-service-management/game-configuration/segmentation/player-custom-properties-qs.md @@ -19,7 +19,7 @@ To get started using Player Custom Properties, follow the guides here. ## Creating, modifying, deleting Player Custom Properties in Game Manager - Sign in to [Game Manager](https://developer.playfab.com/en-US/login). + Sign in to [Game Manager](https://developer.playfab.com). - Go to the **Players** page and select a player. - Select the **Player Data** tab. - Select the **Custom** subtab. @@ -60,7 +60,7 @@ To modify a custom property: > [!NOTE] > V1 and V2 PlayStream events can be used to set or update custom properties. -- Sign in to [Game Manager](https://developer.playfab.com/en-US/login). +- Sign in to [Game Manager](https://developer.playfab.com). - Go to the **Automation** page and select the **Rules** tab. - Select the **New rule** button on the top right of the page. - Populate the **Name** and **Event** type text boxes. V1 events are prefixed with **com.playfab.** or **title.** whereas v2 events are prefixed with **playfab.** or **custom.** diff --git a/playfab-docs/live-service-management/gamemanager/quickstart.md b/playfab-docs/live-service-management/gamemanager/quickstart.md index 0084721ca..4a7b05bc3 100644 --- a/playfab-docs/live-service-management/gamemanager/quickstart.md +++ b/playfab-docs/live-service-management/gamemanager/quickstart.md @@ -19,7 +19,7 @@ Get started with PlayFab by using Game Manager to create your PlayFab account, c ## Create a PlayFab account -On the [PlayFab sign up](https://developer.playfab.com/en-us/sign-up) screen, you can create a PlayFab specific account or use your Microsoft account to sign in. +On the [PlayFab sign up](https://developer.playfab.com) screen, you can create a PlayFab specific account or use your Microsoft account to sign in. When you've signed in, PlayFab prompts you enter your contact information and studio information. If you haven't finalized the game studio name, you can change it later. diff --git a/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md b/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md index 777cfeddd..0894206df 100644 --- a/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md +++ b/playfab-docs/live-service-management/service-gateway/automation/cloudscript-af/quickstart.md @@ -25,7 +25,7 @@ There are a couple of steps needed to get started with PlayFab C# CloudScript. - To minimize latency of your CloudScript using Azure Functions place them in the *US-West*, *US-West 2*, or *US-West 3* Azure regions. - **Security Note:** From a security perspective, you should make sure to only use a given function secret with PlayFab and not use it for calling the same function from any other source. - **Security Note:** For queued functions, you should set up a distinct storage account for the queues used for the queue trigger. -- A [PlayFab](https://playfab.com/) account. +- A [PlayFab](https://developer.playfab.com/) account. > [!NOTE] > PlayFab Azure Functions can use the Azure Functions V2 runtime or greater, and .NET Core 2 or greater. We recommend that you use the latest version (currently Azure Functions V4 and .NET 6). diff --git a/playfab-docs/multiplayer/lobby/lobby-getting-started.md b/playfab-docs/multiplayer/lobby/lobby-getting-started.md index e5f8bac2c..7a1b739c0 100644 --- a/playfab-docs/multiplayer/lobby/lobby-getting-started.md +++ b/playfab-docs/multiplayer/lobby/lobby-getting-started.md @@ -24,7 +24,7 @@ This article describes how to set up the development environment for Azure PlayF ## Prerequisites -You need a [PlayFab account](https://playfab.com) to use PlayFab Lobbies. For instructions to create an account, see [Quickstart: Game Manager](../../live-service-management/gamemanager/quickstart.md). +You need a [PlayFab account](https://developer.playfab.com) to use PlayFab Lobbies. For instructions to create an account, see [Quickstart: Game Manager](../../live-service-management/gamemanager/quickstart.md). ## Download and set up the PlayFab Multiplayer SDK diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-plugin-quickstart.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-plugin-quickstart.md index 7ed4a4d36..f24e915e4 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-plugin-quickstart.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-plugin-quickstart.md @@ -22,7 +22,7 @@ This quickstart helps you make your first API calls using the PlayFab Multiplaye ## Requirements -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). - An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for professional use, see [Download Unity](https://unity3d.com/get-unity/download). Check on Unity support in documentation of your specific platform if needed. The minimum supported Unity version is Unity 2017 LTS. - A Unity Project – this can be any of the following: diff --git a/playfab-docs/multiplayer/matchmaking/quickstart-client-sdk.md b/playfab-docs/multiplayer/matchmaking/quickstart-client-sdk.md index 30d22c207..a0e702ed1 100644 --- a/playfab-docs/multiplayer/matchmaking/quickstart-client-sdk.md +++ b/playfab-docs/multiplayer/matchmaking/quickstart-client-sdk.md @@ -27,7 +27,7 @@ The matchmaking service handles finding a match among tickets in a queue. When a ## Prerequisites -You need a [PlayFab account](https://playfab.com) to use PlayFab Matchmaking. For instructions to create an account, see [Quickstart: Game Manager](../../live-service-management/gamemanager/quickstart.md). +You need a [PlayFab account](https://developer.playfab.com) to use PlayFab Matchmaking. For instructions to create an account, see [Quickstart: Game Manager](../../live-service-management/gamemanager/quickstart.md). ## Configure a matchmaking queue in Game Manager diff --git a/playfab-docs/multiplayer/networking/android-specific-requirements.md b/playfab-docs/multiplayer/networking/android-specific-requirements.md index 254c4c103..54ba96004 100644 --- a/playfab-docs/multiplayer/networking/android-specific-requirements.md +++ b/playfab-docs/multiplayer/networking/android-specific-requirements.md @@ -18,7 +18,7 @@ This document lists the basic prerequisites and requirements necessary to integr Before you start this tutorial, please ensure that the following prerequisites have been met: -1. You created a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +1. You created a [PlayFab developer account](https://developer.playfab.com). 1. You created a PlayFab Title and your title has been allow-listed for PlayFab Party. diff --git a/playfab-docs/multiplayer/networking/apple-specific-requirements.md b/playfab-docs/multiplayer/networking/apple-specific-requirements.md index 59ef04935..45bbd4b57 100644 --- a/playfab-docs/multiplayer/networking/apple-specific-requirements.md +++ b/playfab-docs/multiplayer/networking/apple-specific-requirements.md @@ -17,7 +17,7 @@ This document lists the basic prerequisites and requirements necessary to integr ## Prerequisites Before you start this tutorial, ensure that the following prerequisites have been met: -1. You've created a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up) +1. You've created a [PlayFab developer account](https://developer.playfab.com) 2. You've created a PlayFab Title and your title has been allow-listed for PlayFab Party 3. You have Xcode version 10.2.1 or higher installed 4. You have access to the [PlayFab Party platforms repository](https://github.com/PlayFab/PlayFabParty) diff --git a/playfab-docs/multiplayer/networking/party-tutorial-requestpartyservice.md b/playfab-docs/multiplayer/networking/party-tutorial-requestpartyservice.md index 1cec37a60..5498e1f6d 100644 --- a/playfab-docs/multiplayer/networking/party-tutorial-requestpartyservice.md +++ b/playfab-docs/multiplayer/networking/party-tutorial-requestpartyservice.md @@ -22,7 +22,7 @@ This tutorial describes the steps to request parties from your own services rath You need a PlayFab account and have enabled the Party feature. -1. Create or sign in to your [PlayFab account](https://playfab.com). +1. Create or sign in to your [PlayFab account](https://developer.playfab.com). 2. [Enable Party feature via Game Manager](enable-party.md) from your PlayFab account. 3. Download and set up Party SDK. For download links, see [Party SDKs](party-sdks.md). diff --git a/playfab-docs/multiplayer/networking/party-unity-plugin-quickstart.md b/playfab-docs/multiplayer/networking/party-unity-plugin-quickstart.md index 4eb5b90e0..02a47a7b9 100644 --- a/playfab-docs/multiplayer/networking/party-unity-plugin-quickstart.md +++ b/playfab-docs/multiplayer/networking/party-unity-plugin-quickstart.md @@ -20,7 +20,7 @@ This quickstart helps you install the Party SDK for Unity and make your first AP ## Requirements -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). - An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for professional use, see [Download Unity](https://unity3d.com/get-unity/download). Check on Unity support in documentation of your specific platform if needed. The minimum supported Unity version is Unity 2017 LTS. - A Unity Project, which can be any of the following options: diff --git a/playfab-docs/multiplayer/networking/quickstart.md b/playfab-docs/multiplayer/networking/quickstart.md index e328f79b1..6fceaf2fc 100644 --- a/playfab-docs/multiplayer/networking/quickstart.md +++ b/playfab-docs/multiplayer/networking/quickstart.md @@ -26,7 +26,7 @@ For a deeper understanding, consult the linked reference and conceptual document You need a PlayFab account, and you *must enable* the Party feature to start using Party. -1. Create or sign in to your [PlayFab account](https://playfab.com). For instructions, see [Quickstart: Game Manager](../../live-service-management/gamemanager/quickstart.md). +1. Create or sign in to your [PlayFab account](https://developer.playfab.com). For instructions, see [Quickstart: Game Manager](../../live-service-management/gamemanager/quickstart.md). 1. [Enable Party feature via Game Manager](enable-party.md) from your PlayFab account. ## Platform Prerequisites diff --git a/playfab-docs/multiplayer/servers/build-definition.md b/playfab-docs/multiplayer/servers/build-definition.md index f2821f042..638a08a57 100644 --- a/playfab-docs/multiplayer/servers/build-definition.md +++ b/playfab-docs/multiplayer/servers/build-definition.md @@ -12,11 +12,11 @@ ms.localizationpriority: medium # Build definition and configuration -This topic describes the parameters you need to specify when deploying/creating a Virtual Machine (VM)/game server build. +This article describes the parameters you need to specify when deploying/creating a Virtual Machine (VM)/game server build. A build is created by specifying its *build definition* and *build configuration*. -Build definition **cannot be modified** after it is created. This requires you to select what Virtual Machines (VMs) you want, upload your PlayFab Multiplayer Game Server Build, assets, certificates, and more. +Build definition **cannot be modified** after it's created. This requires you to select what Virtual Machines (VMs) you want, upload your PlayFab Multiplayer Game Server Build, assets, certificates, and more. Build configuration determines how your game scales across Azure. This **can be modified at any time** in a build's life. @@ -35,9 +35,9 @@ For sample values you can use to deploy a simple server, see [Walk-through of de | Servers per machine | Number of game servers hosted on each VM. The number of cores in the VM is split by the number of servers. | | | Virtual machine OS | Select Windows or Linux platform. | | | Container | The container that will host your game server. | For Windows, you can simply select the managed Windows Server Core containers. For Linux-based VMs, see [Deploying Linux-based builds](deploying-linux-based-builds.md).| -| Assets | Files you want uploaded on the servers. You can upload multiple assets but one of the assets **must** contain your [PlayFab Multiplayer Game Server Build](#).
All assets combined should be less than 10GB in size and must be in *zip*, *tar.gz* or *tar* file type.
Each asset has a mount path associated with it. This specifies where it is mounted in the container file system.| Asset filenames can only contain alphanumeric characters, underscores, hyphens, and periods. You can use C:\Assets as the typical mount path. What this means that PlayFab will unzip your assets and mount it **in the container file-system** (not the VM) as a folder in the **C** drive under Assets. | +| Assets | Files you want uploaded on the servers. You can upload multiple assets but one of the assets **must** contain your [PlayFab Multiplayer Game Server Build](#).
All assets combined should be less than 10 GB in size and must be in *zip*, *tar.gz, or *tar* file type.
Each asset has a mount path associated with it. This specifies where it's mounted in the container file system.| Asset filenames can only contain alphanumeric characters, underscores, hyphens, and periods. You can use C:\Assets as the typical mount path. What this means that PlayFab will unzip your assets and mount it **in the container file-system** (not the VM) as a folder in the **C** drive under Assets. | | Start command | The command to run when the game server starts, make sure to include any arguments that you need. | | -| Network | Define the port name, number, and protocol (TCP or UDP) to be used for incoming network traffic. Outgoing (or solicited) network flows do not need to be configured. For more networking information, see [Connecting clients to game servers](connecting-clients-to-game-servers.md).| | +| Network | Define the port name, number, and protocol (TCP or UDP) to be used for incoming network traffic. Outgoing (or solicited) network flows don't need to be configured. For more networking information, see [Connecting clients to game servers](connecting-clients-to-game-servers.md).| | | Certificate (optional) | Upload certificates for the game server. This is a .pfx (Windows) or .pem (Linux) file containing the certificate to be installed within the container. Certificate names can only contain letters and numbers. No spaces or special characters such as dashes and underscores. | Typically, the certificate for service-to-service authentication is installed through this configuration. | | Metadata (optional) | A set of property-values that can be retrieved using GSDK | | @@ -55,7 +55,7 @@ Build configuration is determined by the following list of parameters. When sele This is the fastest way to view what's required when deploying/creating a VM build. -* Log into your developer account on [PlayFab.com](https://playfab.com) +* Log into your developer account on [PlayFab.com](https://developer.playfab.com) * Go to **My Studios and Titles** page and select your game title to display the dashboard * Go to **Multiplayer** > **Servers** page, select **New Build** at the top right to create a new build diff --git a/playfab-docs/multiplayer/servers/deploy-using-powershell-api.md b/playfab-docs/multiplayer/servers/deploy-using-powershell-api.md index 0a314595d..5faaf21fe 100644 --- a/playfab-docs/multiplayer/servers/deploy-using-powershell-api.md +++ b/playfab-docs/multiplayer/servers/deploy-using-powershell-api.md @@ -24,7 +24,7 @@ If this is your first time deploying a build, we recommend deploying a build usi ## Get your title ID and developer secret key * Get your PlayFab title ID - * Log into your developer account on [PlayFab.com](https://playfab.com) + * Log into your developer account on [PlayFab.com](https://developer.playfab.com) * In Game Manager, go to **My Studios and Titles** page. Look for your game title and get the PlayFab game title ID * Get the developer secret key for the title diff --git a/playfab-docs/multiplayer/servers/enable-playfab-multiplayer-servers.md b/playfab-docs/multiplayer/servers/enable-playfab-multiplayer-servers.md index 01974a897..c8d555a79 100644 --- a/playfab-docs/multiplayer/servers/enable-playfab-multiplayer-servers.md +++ b/playfab-docs/multiplayer/servers/enable-playfab-multiplayer-servers.md @@ -12,16 +12,16 @@ ms.localizationpriority: medium # Enable PlayFab Multiplayer Server feature -PlayFab Multiplayer Server is not automatically enabled when you sign up for a PlayFab account. In order to use and view the servers, you need to enable the feature from Game Manager or use API/PowerShell. +PlayFab Multiplayer Server isn't automatically enabled when you sign up for a PlayFab account. In order to use and view the servers, you need to enable the feature from Game Manager or use API/PowerShell. -You have to enable the feature using Game Manager if you do not yet have a payment method on the account. +You have to enable the feature using Game Manager if you don't yet have a payment method on the account. -Certain servers have limited free usage and capacity limits. They can be used during evaluation and development. If you are enrolled in paid pricing plans, you may request for additional server cores. To learn more, see [Managing Server cores quota](quota-changes.md). +Certain servers have limited free usage and capacity limits. They can be used during evaluation and development. If you're enrolled in paid pricing plans, you may request for additional server cores. To learn more, see [Managing Server cores quota](quota-changes.md). ## Enable using Game Manager -1. Log into your developer account on [PlayFab.com](https://playfab.com) -2. Go to **My Studios and Titles** page and select your game title to display the dashboard. If you have not created one, you have to create a new title. +1. Log into your developer account on [PlayFab.com](https://developer.playfab.com) +2. Go to **My Studios and Titles** page and select your game title to display the dashboard. If you haven't created one, you have to create a new title. 3. Go to **Multiplayer** > **Servers** page 4. Select **Enable** diff --git a/playfab-docs/multiplayer/servers/quickstart-for-multiplayer-servers-api-powershell.md b/playfab-docs/multiplayer/servers/quickstart-for-multiplayer-servers-api-powershell.md index d8f7fada1..cd2e391f8 100644 --- a/playfab-docs/multiplayer/servers/quickstart-for-multiplayer-servers-api-powershell.md +++ b/playfab-docs/multiplayer/servers/quickstart-for-multiplayer-servers-api-powershell.md @@ -27,7 +27,7 @@ Make sure you have completed the following steps. ## 1. Get your title ID and developer secret key * Get your PlayFab title ID - * Log into your developer account on [PlayFab.com](https://playfab.com) + * Log into your developer account on [PlayFab.com](https://developer.playfab.com) * In Game Manager, go to **My Studios and Titles** page. Look for your game title and get the PlayFab game title ID * Get the developer secret key for the title diff --git a/playfab-docs/multiplayer/servers/quickstart-for-multiplayer-servers-game-manager.md b/playfab-docs/multiplayer/servers/quickstart-for-multiplayer-servers-game-manager.md index 245ac30b1..44601ca14 100644 --- a/playfab-docs/multiplayer/servers/quickstart-for-multiplayer-servers-game-manager.md +++ b/playfab-docs/multiplayer/servers/quickstart-for-multiplayer-servers-game-manager.md @@ -28,7 +28,7 @@ Make sure you've completed the following steps. ## Steps -1. Log into your developer account on [PlayFab.com](https://playfab.com) +1. Log into your developer account on [PlayFab.com](https://developer.playfab.com) 2. Go to **My Studios and Titles** page and select your game title to display the dashboard 3. Go to **Multiplayer** > **Servers** page, select **New Build** at the top right to create a new build 4. Use "My build" as the Build Name diff --git a/playfab-docs/multiplayer/servers/using-playfab-servers-to-host-games.md b/playfab-docs/multiplayer/servers/using-playfab-servers-to-host-games.md index 425f0e571..dd23556de 100644 --- a/playfab-docs/multiplayer/servers/using-playfab-servers-to-host-games.md +++ b/playfab-docs/multiplayer/servers/using-playfab-servers-to-host-games.md @@ -20,7 +20,7 @@ As part of configuration process, you would upload a game server build that woul ## What you need -* Developer account on [PlayFab.com](https://playfab.com) +* Developer account on [PlayFab.com](https://developer.playfab.com) * [Enable PlayFab Multiplayer Servers feature](enable-playfab-multiplayer-servers.md) * Your server-client game source code diff --git a/playfab-docs/multiplayer/servers/windows-runner-sample.md b/playfab-docs/multiplayer/servers/windows-runner-sample.md index 58374f669..b00478fc6 100644 --- a/playfab-docs/multiplayer/servers/windows-runner-sample.md +++ b/playfab-docs/multiplayer/servers/windows-runner-sample.md @@ -20,14 +20,14 @@ This tutorial lists the steps to get the sample set up ready for use with the Pl 1. [Configure API feature option](#configure-api-feature-option) 2. Create a PlayFab Multiplayer Game Server Build: [Server set up](#server-set-up) 3. [Create servers by deploying a build](#create-servers-by-deploying-a-build) -4. Request multiplayer servers: [Client set up](#client-set-up). This is needed so you can start a client that connects to the servers +4. Request multiplayer servers: [Client set up](#client-set-up). This request is needed so you can start a client that connects to the servers ## Configure API feature option > [!Note] > This step is needed only for running this sample. You do not need to allow clients to start games unless your title requires this set up. -* Log into your developer account on [PlayFab.com](https://playfab.com) to use the Game Manager portal +* Log into your developer account on [PlayFab.com](https://developer.playfab.com) to use the Game Manager portal * Select your game title * Select the settings icon > __API features__ as shown in the image below. @@ -44,16 +44,16 @@ Describes how to get the PlayFab Multiplayer Game Server Build. * [PlayFab Game Server SDK](https://github.com/PlayFab/gsdk) of the PlayFab Multiplayer Server Build for the Windows Runner sample. * If you prefer to build this on your own: * Get the [Windows Runner C# sample](https://github.com/PlayFab/MpsSamples/tree/master/WindowsRunnerCSharp) using standard Git methods or downloading this as a zip file. - * Open the project using Visual Studio 2017 or later. This should automatically trigger dependencies like the latest [PlayFab Game Server SDK (GSDK) nuget package](https://www.nuget.org/packages/com.playfab.csharpgsdk) to be downloaded. - * Compile and build the WindowsRunnerCSharp.csproj in release x64 configuration. You would get a game server build that is integrated with the GSDK, making this a valid PlayFab Multiplayer Game Server Build. - * Go to the bin folder and zip up all the x64 release binaries. There should be no internal folder structure, the zip file should be a simple flat collection of files, as shown in the image below. + * Open the project using Visual Studio 2017 or later. This should automatically trigger dependencies like the latest [PlayFab Game Server SDK (GSDK) NuGet package](https://www.nuget.org/packages/com.playfab.csharpgsdk) to be downloaded. + * Compile and build the WindowsRunnerCSharp.csproj in release x64 configuration. You would get a game server build that is integrated with the GSDK, making it a valid PlayFab Multiplayer Game Server Build. + * Go to the bin folder and zip up all the x64 release binaries. There should be no internal folder structure. The zip file should be a flat collection of files, as shown in the image below. ![GSDK Sample Output](media/tutorials/gsdk-sample-output.png) > [!Tip] -> To cross-check, you can compare your build output with the compiled version provided in the link above. +> To cross-check, you can compare your build output with the compiled version provided in the link. -When you have the zip file, you are ready to start [deploying a build](#create-servers-by-deploying-a-build). +When you have the zip file, you're ready to start [deploying a build](#create-servers-by-deploying-a-build). ## Create servers by deploying a build @@ -62,7 +62,7 @@ You can deploy a build using one of the following methods. * [Use Game Manager to deploy and configure servers](quickstart-for-multiplayer-servers-game-manager.md) * [Use PowerShell to deploy and configure servers](quickstart-for-multiplayer-servers-api-powershell.md) -For some settings, it may be easier to configure using the web interface—Game Manager. +For some settings, it might be easier to configure using the web interface—Game Manager. Next, [set up and run the client](#client-set-up) to connect to the deployed servers. @@ -85,7 +85,7 @@ Describes how to get the Windows Runner client application to connect to the gam * Copy the __titleId__ and __buildId__ and paste it somewhere convenient * Get the [Windows Runner C# sample](https://github.com/PlayFab/MpsSamples/tree/master/WindowsRunnerCSharp) using standard Git methods or downloading this as a zip file. Skip if you have done this earlier. -* Open the project using Visual Studio 2017 or later. This should automatically trigger dependencies like the latest [Game Server SDK nuget package](https://www.nuget.org/packages/com.playfab.csharpgsdk) to be downloaded. +* Open the project using Visual Studio 2017 or later. This should automatically trigger dependencies like the latest [Game Server SDK NuGet package](https://www.nuget.org/packages/com.playfab.csharpgsdk) to be downloaded. * Compile and build the __WindowsRunnerCSharpClient.csproj__ in release x64 configuration * Open Command Prompt and navigate to the output folder of this project * Run the WindowsRunnerCSharpClient using this command line, replacing \ and \ with the values above: __dotnet WindowsRunnerCSharpClient.dll --titleId \ --buildId \__ diff --git a/playfab-docs/player-progression/player-data/getting-player-profiles.md b/playfab-docs/player-progression/player-data/getting-player-profiles.md index 49ec4081b..70b505348 100644 --- a/playfab-docs/player-progression/player-data/getting-player-profiles.md +++ b/playfab-docs/player-progression/player-data/getting-player-profiles.md @@ -24,7 +24,7 @@ In this tutorial you learn how to: ## Requirements -* A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +* A [PlayFab developer account](https://developer.playfab.com). * An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for professional use, see [Download Unity](https://unity3d.com/get-unity/download). > [!NOTE] > The PlayFab Unity3D SDK supports Unity Editor version 5.3 (released December 2015) and higher. @@ -130,7 +130,7 @@ By default, the **ALLOW CLIENT ACCESS TO PROFILE PROPERTIES:** had only **Displa To configure additional constraints for the title: -* In [Game Manager](https://developer.playfab.com/en-US/login), select your title. +* In [Game Manager](https://developer.playfab.com), select your title. * Select the gear icon in the upper left-hand corner, then select **Title settings**. * Select the **Client Profile Options** tab. * To enable both **Created** and **LastLogin** in the [ProfileConstraints](xref:titleid.playfabapi.com.server.accountmanagement.getplayerprofile#playerprofileviewconstraints), check **Creation date** and **Last login time**, then select **SAVE CLIENT PROFILE OPTIONS**. diff --git a/playfab-docs/player-progression/player-data/quickstart.md b/playfab-docs/player-progression/player-data/quickstart.md index 06a24687f..79f21d806 100644 --- a/playfab-docs/player-progression/player-data/quickstart.md +++ b/playfab-docs/player-progression/player-data/quickstart.md @@ -21,7 +21,7 @@ Player data is information that applies to an individual player or player group ## Requirements -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). - An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for professional use, see [Download Unity](https://unity3d.com/get-unity/download). > [!NOTE] > The PlayFab Unity3D SDK supports Unity Editor version 5.3 (released December 2015) and higher. diff --git a/playfab-docs/player-progression/player-data/using-player-publisher-data.md b/playfab-docs/player-progression/player-data/using-player-publisher-data.md index cd1b0abc1..f256faa24 100644 --- a/playfab-docs/player-progression/player-data/using-player-publisher-data.md +++ b/playfab-docs/player-progression/player-data/using-player-publisher-data.md @@ -16,7 +16,7 @@ Rewards usually involve *other* systems outside of player data, so this example ## Requirements -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). - A player must sign into *both* titles using the same credentials. One approach is to use **Recoverable Credentials**, as described in our [Login Basics and Best Practices](../../identity/player-identity/login/login-basics-best-practices.md) tutorial. To add a **Recoverable** login to an anonymous account, see our [Account Linking](../../identity/player-identity/login/quickstart.md) tutorial. - This example requires a working knowledge of [CloudScript](../../live-service-management/service-gateway/automation/cloudscript/writing-custom-cloudscript.md): - Our example demonstrates basic data security to avoid player cheating. One could likewise use the server API on a custom game server, if the title makes use of them. diff --git a/playfab-docs/player-progression/statistics/quickstart-statistics.md b/playfab-docs/player-progression/statistics/quickstart-statistics.md index 3189dfbd5..2122ab6f4 100644 --- a/playfab-docs/player-progression/statistics/quickstart-statistics.md +++ b/playfab-docs/player-progression/statistics/quickstart-statistics.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Quickstart statistics In this guide, we're going to see how to set up the development environment for the Statistics service. We're also going -to learn how to create a quick leaderboard from our website [Game Manager](https://developer.playfab.com/en-US/login). +to learn how to create a quick leaderboard from our website [Game Manager](https://developer.playfab.com). ## Prerequisites @@ -59,7 +59,7 @@ PlayFabSettings.staticSettings.DeveloperSecretKey = ""; // Change this to your t ## Creating a title and getting the secret key -- Log in to https://playfab.com/ +- Log in to https://developer.playfab.com/ - Create a title - Find the Title ID in the API Features section under settings. - Generate secret key: diff --git a/playfab-docs/pricing/support.md b/playfab-docs/pricing/support.md index 47f9373fe..4f233e313 100644 --- a/playfab-docs/pricing/support.md +++ b/playfab-docs/pricing/support.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Accessing PlayFab Technical Support PlayFab offers a range of support options designed to meet the needs of developers across various stages of development and account tiers. Whether you're just getting started or actively managing a live title, you can access support through public documentation, community discord, or direct technical assistance. -Support availability is based on your account plan, with higher tiers offering expanded access and faster response times. Customers may upgrade their plans to unlock additional support features. +Support availability is based on your account plan, with higher tiers offering expanded access and faster response times. Customers can upgrade their plans to unlock additional support features. ## Support Offerings Overview @@ -21,8 +21,8 @@ Support availability is based on your account plan, with higher tiers offering e |:---------------------------------- |:-----------------------------------|:-----------------------------------| | **Documentation** | Public API reference, tutorials, samples, and feature guides. | Open to all | | **Discord Community** | Community-based support and discussion forums via Discord. | Open to all | -| **Account Help** | Direct support for non-technical administrative issues | Open to all PlayFab Developers Accounts | -| **Support Tickets** | Direct support for technical issues and service implemetation questions. |Standard Plans and above| +| **Account Help** | Direct support for nontechnical administrative issues | Open to all PlayFab Developers Accounts | +| **Support Tickets** | Direct support for technical issues and service implementation questions. |Standard Plans and above| | **Emergency Escalations** | Fastest incident response for service-impacting emergencies. |Premium Plans only | ## Support Offerings @@ -45,30 +45,30 @@ Support availability is based on your account plan, with higher tiers offering e ### ACCOUNT HELP -**Purpose:** Use PlayFab Account Help to submit non-technical inquiries related to account access, billing, plan management, sales, or other administrative support. +**Purpose:** Use PlayFab Account Help to submit nontechnical inquiries related to account access, billing, plan management, sales, or other administrative support. **Minimum Required Account Plan:** PlayFab account is needed. Available to all PlayFab developers, including free-tier accounts. **How to access:** PlayFab Developers can access the **Account Help** page in Game Manager. -1. Log in to [PlayFab.com](https://playfab.com). +1. Log in to [PlayFab.com](https://developer.playfab.com). 2. Navigate to the **Studio-level** "..." section (ellipsis menu). 3. Select Account Help. 4. Complete the request form by selecting appropriate Problem Type and Sub-Type fields with description of the problem. -5. Submit the ticket. Expect a response within 3 business days. +5. Submit the ticket. Expect a response within three business days. > [!NOTE] > To streamline support access for effective issue resolution, PlayFab has updated its support experience across both PlayFab.com and Game Manager. This includes the deprecation of the “Contact Us” form on PlayFab.com, introduction of the Account Help support for all PlayFab developers. -> For login-related issues, please use the self-service account recovery flow provided through Microsoft Entra ID. +> For login-related issues, use the self-service account recovery flow provided through Microsoft Entra ID. ### SUPPORT TICKET SUBMISSION -**Purpose:** Use support tickets to understand how to use a particular PlayFab feature, or to request help with a technical problem, or to report a bug. Customers with paid accounts may submit support tickets directly to the PlayFab team through the "Contact Us" Page in Game Manager. Customers will receive a response within 1 business day. +**Purpose:** Use support tickets to understand how to use a particular PlayFab feature, or to request help with a technical problem, or to report a bug. Customers with paid accounts can submit support tickets directly to the PlayFab team through the "Contact Us" Page in Game Manager. Customers will receive a response within one business day. **Minimum Required Account Plan:** Standard Account Plan **How to access:** Qualified accounts can access the **Contact Us** page in Game Manager: -1. Log in to [PlayFab.com](https://playfab.com). +1. Log in to [PlayFab.com](https://developer.playfab.com). 2. Navigate to the **Title Overview** page of the title needing support. 3. To access the help menu, select the **?** in the top right navigation bar. 4. Select **Contact Us** and fill out the support form. @@ -80,13 +80,13 @@ If you recently requested an upgrade, support ticket submission becomes availabl **Purpose:** Provides 24/7 access to PlayFab's on-call engineering team in the event of critical service-impacting issues. This provides fastest incident response time to customers during emergencies. > [!NOTE] -> Emergency escalations should be used sparingly and only in the case of high-impact service errors or outtages. +> Emergency escalations should be used sparingly and only in the case of high-impact service errors or outages. **Minimum Required Account Plan:** Premium Account Plan **How to access:** Qualified accounts can use the emergency escalation option via the **Contact Us** page in Game Manager: -1. Log in to [PlayFab.com](https://playfab.com). +1. Log in to [PlayFab.com](https://developer.playfab.com). 2. Navigate to the **Title Overview** page of the title needing support. 3. Select the **?** in the top right navigation bar to access the drop-down menu. 4. Select **Contact Us** to access the form. diff --git a/playfab-docs/pricing/title-launches.md b/playfab-docs/pricing/title-launches.md index ed8d87a37..cc7a6ebf9 100644 --- a/playfab-docs/pricing/title-launches.md +++ b/playfab-docs/pricing/title-launches.md @@ -43,7 +43,7 @@ Titles may only be changed to Live in Studios owned by paid accounts. Follow the To launch a title within a paid account plan: -1. Sign in to [https://playfab.com/](https://playfab.com/) +1. Sign in to [https://developer.playfab.com/](https://developer.playfab.com/) 2. Navigate to the **My Studios** page and identify the **Development mode** title to be launched. diff --git a/playfab-docs/sdks/c-sharp/quickstart.md b/playfab-docs/sdks/c-sharp/quickstart.md index 52210cccc..a39c5aad8 100644 --- a/playfab-docs/sdks/c-sharp/quickstart.md +++ b/playfab-docs/sdks/c-sharp/quickstart.md @@ -20,7 +20,7 @@ This quickstart helps you make your first PlayFab API call in the using the Clie ## Requirements -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). - An installation of [Visual Studio](https://visualstudio.microsoft.com/). ## CSharp project setup diff --git a/playfab-docs/sdks/cocos2d-x/quickstart.md b/playfab-docs/sdks/cocos2d-x/quickstart.md index 75f2acfc3..05d2e4fc6 100644 --- a/playfab-docs/sdks/cocos2d-x/quickstart.md +++ b/playfab-docs/sdks/cocos2d-x/quickstart.md @@ -14,13 +14,13 @@ ms.localizationpriority: medium This quickstart assists you in making your first PlayFab API call in the Cocos2d-x engine. -Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com). ## Cocos2d-x project setup OS: This guide is written for Windows 10, using Visual Studio 2015. Cocos works on most modern OSs and environments. The installation instructions are similar, but different for each combination. -If you are building for other platforms, the files you need are the same, but you will need to do the project setup yourself. Visual Studio 2013 will have identical steps, but the screenshots provided here will look a bit different from yours. +If you're building for other platforms, the files you need are the same, but you'll need to do the project setup yourself. Visual Studio 2013 has identical steps, but the screenshots provided here look a bit different from yours. 1. Download and install Cocos2d-x - [https://www.cocos2d-x.org/download](https://www.cocos2d-x.org/download) @@ -38,8 +38,8 @@ If you are building for other platforms, the files you need are the same, but yo - In the new console window enter this command: - `cocos new CocosGettingStarted -l cpp` - - Make sure your target sub-directory (**CocosGettingStarted**) does not already exist - This command will fail if the folder already exists. - - If you get a message that "'cocos' is not recognized as an internal or external command", you have not configured the cocos installation correctly (Go back to the Cocos windows installation guide). + - Make sure your target sub-directory (**CocosGettingStarted**) doesn't already exist - This command will fail if the folder already exists. + - If you get a message that "'cocos' isn't recognized as an internal or external command", you haven't configured the cocos installation correctly (Go back to the Cocos windows installation guide). - If successful, there will be a new folder **CocosGettingStarted**. This guide will refer to that directory location as `{CocosGettingStarted}`. - Successful output should appear similar to the example provided below. @@ -87,9 +87,9 @@ PlayFab uses several Cocos libraries that have to be manually added to the depen `$(ProjectDir)..\cocos2d\external\zlib\include;$(ProjectDir)..\cocos2d\external\curl\include\win32;$(EngineRoot)cocos\audio\include;$(EngineRoot)external;$(EngineRoot)external\chipmunk\include\chipmunk;$(EngineRoot)extensions;..\Classes;..;%(AdditionalIncludeDirectories);$(_COCOS_HEADER_WIN32_BEGIN);$(_COCOS_HEADER_WIN32_END);..\cocos2d` > [!NOTE] -> We are adding curl and zlib, which are libraries that come with Cocos, but are not enabled by default. +> We're adding curl and zlib, which are libraries that come with Cocos, but aren't enabled by default. -Your CocosGettingStarted project should now compile (and even run), but we are not yet making any PlayFab API calls. +Your CocosGettingStarted project should now compile (and even run), but we aren't yet making any PlayFab API calls. Installation complete! @@ -211,13 +211,13 @@ These files take the existing HelloWorldScene that is part of the new-Cocos-proj ## Finish and execute 1. Build and Execute your Cocos Project: Dropdowns -> Debug -> Start Debugging. -2. This may prompt you to build. Select **Yes**. +2. This will prompt you to build. Select **Yes**. 3. You should see a screen that says: **Congratulations, you made your first successful API call!** -4. Now, you can start making other api calls, and building your game. +4. Now, you can start making other API calls, and building your game. For a list of all available client API calls, see our [PlayFab API References](../../api-references/index.md) documentation. Happy coding! @@ -228,8 +228,8 @@ This optional last section describes each part of source code above, in detail. - `HelloWorldScene.h` - This is only trivially modified from the default `HelloWorldScene.h` generated by Cocos. - - Specifically, it defines some Cocos GUI we are using, and the prototype for `OnLoginSuccess` and `OnLoginFail`. - - Everything else is just standard Cocos Engine functions. + - Specifically, it defines some Cocos GUI we're using, and the prototype for `OnLoginSuccess` and `OnLoginFail`. + - Everything else is standard Cocos Engine functions. - `HelloWorldScene.cpp` - `createScene()` is a standard Cocos Engine function. @@ -241,7 +241,7 @@ This optional last section describes each part of source code above, in detail. - `PlayFab::ClientModels::LoginWithCustomIDRequest request;` - Most PlayFab API methods require input parameters, and those input parameters are packed into a request object. - Every API method requires a unique request object, with a mix of optional and mandatory parameters. - - For `LoginWithCustomIDRequest`, there is a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. + - For `LoginWithCustomIDRequest`, there's a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. - For login, most developers will want to use a more appropriate login method. - See the PlayFab Login documentation for a list of all login methods, and input parameters. Common choices are: - `LoginWithAndroidDeviceID` @@ -252,7 +252,7 @@ This optional last section describes each part of source code above, in detail. - This begins the async request to `LoginWithCustomID`, and will invoke the `OnLoginSuccess` or `OnLoginFail` function when complete. - `update(float delta)` - - Simply setting the `statusMsg` variable does not update the on-screen text. + - Simply setting the `statusMsg` variable doesn't update the on-screen text. - This function sets the GUI text to match the contents of `statusMsg` every tick (not very efficient). - `OnLoginSuccess(result, customData)` @@ -263,14 +263,14 @@ This optional last section describes each part of source code above, in detail. - If the error-function is called, your API call has failed. - API calls can fail for many reasons, and you should always attempt to handle failure. - Why API calls fail (In order of likelihood) - - `PlayFabSettings.TitleId` is not set. If you forget to set titleId to your title, then nothing will work. + - `PlayFabSettings.TitleId` isn't set. If you forget to set titleId to your title, then nothing will work. - In Cocos, the curl library will probably just crash your game if you fail to set titleId correctly. - - Request parameters. If you have not provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. + - Request parameters. If you haven't provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. - Device connectivity issue. Cell phones lose/regain connectivity constantly, and so any API call at any time can fail randomly, and then work immediately after. Going into a tunnel can disconnect you completely. - PlayFab server issue. As with all software, there can be issues. See our release notes for updates. - - The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. - - If you are having difficulty debugging an issue, and the information within the error callback is not sufficient, please visit us on our forums. + - The internet isn't 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. + - If you're having difficulty debugging an issue, and the information within the error callback isn't sufficient, visit us on our forums. - - customData is a void-pointer which can be used in any way to establish context. - - In C++, it is harder to maintain the context of an API call, so we added the `customData` parameter, which can relay any object to the callback, which can be used however you like to establish context. + - customData is a void-pointer, which can be used in any way to establish context. + - In C++, it's harder to maintain the context of an API call, so we added the `customData` parameter, which can relay any object to the callback, which can be used however you like to establish context. - Thus, if you make API calls to retrieve inventory, you can pass a player, or inventory pointer as `customData`, and update the inventory on that object, in the callback. diff --git a/playfab-docs/sdks/java/quickstart.md b/playfab-docs/sdks/java/quickstart.md index b591416b5..96a305e62 100644 --- a/playfab-docs/sdks/java/quickstart.md +++ b/playfab-docs/sdks/java/quickstart.md @@ -14,7 +14,7 @@ ms.localizationpriority: medium This quickstart lets you get up and running with the PlayFab JavaSDK and simple Java program. -Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com). The goals for this tutorial are: @@ -56,7 +56,7 @@ If asked for the **Module**, select the first one in the list. Ensure that all t ## Project Setup with any IDE -The main requirement is to have JAR files added to the classpath. Please consult the guide for your IDE on how to add JAR files to classpath. +The main requirement is to have JAR files added to the classpath. Consult the guide for your IDE on how to add JAR files to classpath. ## Set up your first API call @@ -163,7 +163,7 @@ This optional last section describes every line in `GettingStarted.java` in deta - `PlayFabClientModels.LoginWithCustomIDRequest request = new PlayFabClientModels.LoginWithCustomIDRequest();` - Most PlayFab API methods require input parameters, and those input parameters are packed into a request object. - Every API method requires a unique request object, with a mix of optional and mandatory parameters. - - For `LoginWithCustomIDRequest`, there is a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. + - For `LoginWithCustomIDRequest`, there's a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. - For login, most developers will want to use a more appropriate login method. - See the PlayFab Login documentation for a list of all login methods, and input parameters. Common choices are: @@ -189,10 +189,10 @@ This optional last section describes every line in `GettingStarted.java` in deta - If (`result.Error != null`), the API call has failed. - API calls can fail for many reasons, and you should always attempt to handle failure. - Why API calls fail (In order of likelihood) - - `PlayFabSettings.TitleId` is not set. If you forget to set `TitleId` to your title, then nothing will work. - - Request parameters. If you have not provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. + - `PlayFabSettings.TitleId` isn't set. If you forget to set `TitleId` to your title, then nothing will work. + - Request parameters. If you haven't provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. - Device connectivity issue. Cell phones lose/regain connectivity constantly, and so any API call at any time can fail randomly, and then work immediately after. Going into a tunnel can disconnect you completely. - PlayFab server issue. As with all software, there can be issues. See our [release notes](../../release-notes/index.md) for updates. - - The internet is not 100% reliable. Sometimes the message is corrupted, or fails to reach the PlayFab server. + - The internet isn't 100% reliable. Sometimes the message is corrupted, or fails to reach the PlayFab server. - - If you are having difficulty debugging an issue, and the information within the error information is not sufficient, please visit us on our [forums](https://community.playfab.com/index.html). + - If you're having difficulty debugging an issue, and the information within the error information isn't sufficient, visit us on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/sdks/javascript/quickstart.md b/playfab-docs/sdks/javascript/quickstart.md index cfd2385f7..52d91f1ec 100644 --- a/playfab-docs/sdks/javascript/quickstart.md +++ b/playfab-docs/sdks/javascript/quickstart.md @@ -16,13 +16,13 @@ Get started with the PlayFab client library for JavaScript to authenticate a pla ## Prerequisites -* A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). For information about creating a Title and finding TitleId, see [Game Manager QuickStart](../../live-service-management/gamemanager/quickstart.md). +* A [PlayFab developer account](https://developer.playfab.com). For information about creating a Title and finding TitleId, see [Game Manager QuickStart](../../live-service-management/gamemanager/quickstart.md). The QuickStart guide works in any operating system capable of running a web browser. ## JavaScript project setup -Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). For information about creating a Title and finding TitleId, see [Game Manager QuickStart](../../live-service-management/gamemanager/quickstart.md). +Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com). For information about creating a Title and finding TitleId, see [Game Manager QuickStart](../../live-service-management/gamemanager/quickstart.md). OS: This guide works in any OS capable of running a web browser. @@ -97,11 +97,11 @@ To look up the correct format for the loginRequest object in this example, see t ## Run the code 1. Open `PlayFabGettingStarted.html` in your favorite browser. -2. Click the **Call LoginWithCustomID** button. +2. Select the **Call LoginWithCustomID** button. 3. You should see the following text in the Result section: "Congratulations, you made your first successful API call!" -At this point, you can start making other api calls, and building your game. +At this point, you can start making other API calls, and building your game. For a list of all available client API calls, see [PlayFab API References](../../api-references/index.md) documentation. @@ -117,7 +117,7 @@ The HTML file has a few important lines: ``` -This line loads the Client-SDK directly from the PlayFab CDN. Our CDN always hosts the latest version of PlayFabSDK. It may be safer for you to download the files, and use a fixed version: [PlayFab JavaScript SDK](https://aka.ms/playfabjavascriptsdkdownload) +This line loads the Client-SDK directly from the PlayFab CDN. Our CDN always hosts the latest version of PlayFabSDK. It might be safer for you to download the files, and use a fixed version: [PlayFab JavaScript SDK](https://aka.ms/playfabjavascriptsdkdownload) ```html @@ -136,9 +136,9 @@ The functions in `PlayFabClientSDK` are named after the corresponding HTTP reque - `var loginRequest = { TitleId: PlayFab.settings.titleId, CustomId: "GettingStartedGuide", CreateAccount: true };` - Most PlayFab API methods require input parameters, and those input parameters are packed into a request object - Every API method requires a unique request object, with a mix of optional and mandatory parameters - - For `LoginWithCustomID`, there is a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. `TitleId` is another mandatory parameter in JavaScript, and it must match `PlayFab.settings.titleId`. + - For `LoginWithCustomID`, there's a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. `TitleId` is another mandatory parameter in JavaScript, and it must match `PlayFab.settings.titleId`. - For information about where to find `TitleId`, see [Game Manager QuickStart](../../live-service-management/gamemanager/quickstart.md). - - In this case, `TitleId`, `customId`, and `CreateAccount` are from the Request Body of `LoginWithCustomID`. The Request Body fields are included as keys and values in the request object. The Session Ticket in the Request Header will be saved from login, so the SessionTicket is not included in the request object. + - In this case, `TitleId`, `customId`, and `CreateAccount` are from the Request Body of `LoginWithCustomID`. The Request Body fields are included as keys and values in the request object. The Session Ticket in the Request Header will be saved from login, so the SessionTicket isn't included in the request object. - `PlayFabClientSDK.LoginWithCustomID(loginRequest, LoginCallback);` - This begins the async request to `LoginWithCustomID`, which will call `LoginCallback` when the API call is complete. @@ -152,7 +152,7 @@ The functions in `PlayFabClientSDK` are named after the corresponding HTTP reque - `LoginCallback` contains two parameters: result, error - When successful, error will be null, and the result object will contain the requested information, according to the API called. - This result contains some basic information about the player, but for most users, login is simply a mandatory step before calling other APIs. - - If error is not `null`, your API call has failed. + - If error isn't `null`, your API call has failed. @@ -162,12 +162,12 @@ The functions in `PlayFabClientSDK` are named after the corresponding HTTP reque - The error object includes the error name, error code, and error message. Together, this information should be sufficient to diagnose your error. - Global API Method Error Codes can be found in PlayFab's [Global API Method Error Codes](../../api-references/global-api-method-error-codes.md). - Why API calls fail (In order of likelihood) - - PlayFabSettings.TitleId is not set. If TitleId is not set, then nothing will work. - - Request parameters. If you have not provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage, error.errorDetails`, or `error.GenerateErrorReport()` for more info. + - PlayFabSettings.TitleId isn't set. If TitleId isn't set, then nothing will work. + - Request parameters. If you haven't provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage, error.errorDetails`, or `error.GenerateErrorReport()` for more info. - Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so any API call at any time can fail randomly, and then work immediately after. Going into a tunnel can disconnect you completely. - PlayFab server issue. As with all software, there can be issues. See our [release notes](../../release-notes/index.md) for updates. - - The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. -- If you are having difficulty debugging an issue, and the information within the error information is not sufficient, please visit us on our [forums](https://community.playfab.com/index.html). + - The internet isn't 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. +- If you're having difficulty debugging an issue, and the information within the error information isn't sufficient, visit us on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/sdks/lua/quickstart-corona.md b/playfab-docs/sdks/lua/quickstart-corona.md index c513a7ea8..5cbc71346 100644 --- a/playfab-docs/sdks/lua/quickstart-corona.md +++ b/playfab-docs/sdks/lua/quickstart-corona.md @@ -14,11 +14,11 @@ ms.localizationpriority: medium This quickstart assists you in making your first PlayFab API call in the Corona engine. -Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com). ## Corona Project Setup -OS: This quickstart is written for Windows 10. However, it should also work well with a Mac. +OS: This quickstart is written for Windows. However, it should also work well with a Mac. 1. Download and install Corona: [https://coronalabs.com/](https://coronalabs.com/). @@ -100,7 +100,7 @@ This optional last section describes each part of our example above, line-by-lin - `local loginRequest = { CustomId = "GettingStartedGuide", CreateAccount = true }` - Most PlayFab API methods require input parameters, and those input parameters are packed into a request object - Every API method requires a unique request object, with a mix of optional and mandatory parameters - - For `LoginWithCustomIDRequest`, there is a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. + - For `LoginWithCustomIDRequest`, there's a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. - `PlayFabClientApi.LoginWithCustomID(loginRequest, {OnLoginSuccess-function}, {OnLoginError-function})` - This begins the async request to `LoginWithCustomID`, which will call the first (`OnLoginSuccess`) callback if successful, or the second (`OnLoginError`) function for failures. - For login, most developers will want to use a more appropriate login method. @@ -114,9 +114,9 @@ This optional last section describes each part of our example above, line-by-lin - `OnLoginError` is any function which accepts a single parameter (error). - API calls can fail for many reasons, and you should always attempt to handle failure. - Why API calls fail (In order of likelihood): - - `PlayFabSettings.TitleId` is not set. If you forget to set `titleId` to your title, then nothing will work. - - Request parameters. If you have not provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. + - `PlayFabSettings.TitleId` isn't set. If you forget to set `titleId` to your title, then nothing will work. + - Request parameters. If you haven't provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. - Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so any API call at any time can fail randomly, and then work immediately after. Going into a tunnel can disconnect you completely. - PlayFab server issue. As with all software, there can be issues. See our [release notes](../../release-notes/index.md) for updates. - - The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. - - If you are having difficulty debugging an issue, and the information within the error information is not sufficient, please visit us on our [forums](https://community.playfab.com/index.html). + - The internet isn't 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. + - If you're having difficulty debugging an issue, and the information within the error information isn't sufficient, visit us on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/sdks/lua/quickstart-defold.md b/playfab-docs/sdks/lua/quickstart-defold.md index 131e2e151..91edd2fb2 100644 --- a/playfab-docs/sdks/lua/quickstart-defold.md +++ b/playfab-docs/sdks/lua/quickstart-defold.md @@ -14,7 +14,7 @@ ms.localizationpriority: medium This quickstart assists you in making your first PlayFab API call using Defold. -Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com). ## Defold project setup @@ -22,7 +22,7 @@ OS: This guide is written for Windows 10. It should also work well with a Mac. 1. Create an account and download defold, or log in at [https://www.defold.com/](https://www.defold.com/) (Uses Google O-Auth): [https://d.defold.com/stable/](https://d.defold.com/stable/). -2. If you have not completed the Defold "Getting Started Tutorial", you should do that now. +2. If you haven't completed the Defold "Getting Started Tutorial", you should do that now. 3. Create a new project on the Defold Dashboard, as shown below. @@ -46,19 +46,19 @@ OS: This guide is written for Windows 10. It should also work well with a Mac. - **main/PfGettingStarted.gui** - - Right-click the "main" folder -> **new** -> **Gui File** -> **PfGettingStarted.gui**. + - Select the "main" folder -> **new** -> **Gui File** -> **PfGettingStarted.gui**. - **main/PfGettingStarted.gui_script** - - Right-click "main" folder -> **new** -> **Gui Script File** -> **PfGettingStarted.gui_script**. + - Select "main" folder -> **new** -> **Gui Script File** -> **PfGettingStarted.gui_script**. 8. Hook up our new GUI in the main.collection. - - Double-click main.collection to open it. + - Select main.collection to open it. - In the Outline panel: - - Right-click **Add Game Object** (Optionally rename to **PfGui**). - - Right-Click the new object, **Add Component From File...** + - Select **Add Game Object** (Optionally rename to **PfGui**). + - Select the new object, **Add Component From File...** - PfGettingStarted.gui (Created above). - The Outline panel viewing main.collection should look like the example shown below. @@ -205,7 +205,7 @@ max_nodes: 512 ## Finish and execute -First, make sure everything is saved and select another tab. Then look for " * " markers - sometimes Defold doesn't refresh. +First, make sure everything is saved and select another tab. Then look for " * " markers - sometimes Defold doesn't refresh. Then, build your game (Ctrl+b or dropdowns: **Project** -> **Build and Launch**). You should see the following text on your screen: @@ -219,14 +219,14 @@ Happy coding! - `PfGettingStarted.gui` - Our instructions for `PfGettingStarted.gui` are for expediency, not instruction. This file is a GUI definition, which adds a text box to the screen, binds it to our other script: `PfGettingStarted.gui_script`. You would NOT typically edit these files in text-form. - - For proper instructions on how to build Defold GUI widgets, please read this guide: + - For proper instructions on how to build Defold GUI widgets, read this guide: - [GUI scenes in Defold](https://www.defold.com/manuals/gui/) - `PfGettingStarted.gui_script` - Require statements and setup. - `PlayFabClientApi` allows you to make Client API calls - This is why you're here. - IPlayFabHttps and PlayFabHttps_Defold: - - The PlayFab Defold plugins are built on the PlayFab LuaSdk. The Lua language does not have a proper HTTPS module. Each game-engine that uses Lua implements their own. These two variables tell PlayFabSdk how to access HTTPS. You only need to do this once in your project, in the first scene. Otherwise it's just required boilerplate + - The PlayFab Defold plugins are built on the PlayFab LuaSdk. The Lua language doesn't have a proper HTTPS module. Each game-engine that uses Lua implements their own. These two variables tell PlayFabSdk how to access HTTPS. You only need to do this once in your project, in the first scene. Otherwise it's required boilerplate - `PlayFabClientApi.settings.titleId = "144"` - Every project using PlayFab should create a unique title in the PlayFab website, which we call Game Manager. Find your `titleId` in Game Manager, and replace `144` with your `titleId`. @@ -237,7 +237,7 @@ Happy coding! - `local loginRequest = { TitleId = PlayFabClientApi.settings.titleId, CustomId = "GettingStartedGuide", CreateAccount = true }` - Most PlayFab API methods require input parameters, and those input parameters are packed into a request object - Every API method requires a unique request object, with a mix of optional and mandatory parameters - - For `LoginWithCustomIDRequest`, there is a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. + - For `LoginWithCustomIDRequest`, there's a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. - For login, most developers will want to use a more appropriate login method - See the [PlayFab Login documentation](xref:titleid.playfabapi.com.client.authentication) for a list of all login methods, and input parameters. Common choices are: - [LoginWithAndroidDeviceID](xref:titleid.playfabapi.com.client.authentication.loginwithandroiddeviceid) @@ -254,14 +254,14 @@ Happy coding! - `function OnLoginFailed(error)` - API calls can fail for many reasons, and you should always attempt to handle failure. - Why API calls fail (In order of likelihood) - - PlayFabSettings.TitleId is not set. If you forget to set titleId to your title, then nothing will work. + - PlayFabSettings.TitleId isn't set. If you forget to set titleId to your title, then nothing will work. - - Request parameters. If you have not provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. + - Request parameters. If you haven't provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. - Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so any API call at any time can fail randomly, and then work immediately after. Going into a tunnel can disconnect you completely. - PlayFab server issue. As with all software, there can be issues. See our [release notes](../../release-notes/index.md) for updates. - - The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. + - The internet isn't 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. - - If you are having difficulty debugging an issue, and the information within the error information is not sufficient, please visit us on our [forums](https://community.playfab.com/index.html) + - If you're having difficulty debugging an issue, and the information within the error information isn't sufficient, visit us on our [forums](https://community.playfab.com/index.html) - `local pfTestOutput = gui.get_node("pfOutput")` - This is another Defold GUI function. It fetches the `pfOutput` GUI object defined in our PfGettingStarted.gui file, and assigns it text to display to the user. diff --git a/playfab-docs/sdks/nodejs/quickstart.md b/playfab-docs/sdks/nodejs/quickstart.md index 3b4d9fe83..901e08a4f 100644 --- a/playfab-docs/sdks/nodejs/quickstart.md +++ b/playfab-docs/sdks/nodejs/quickstart.md @@ -18,7 +18,7 @@ Get started with the PlayFab client library for NodeJS to make your first PlayFa ## Prerequisites -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). For information about creating a Title and finding TitleId, see [Game Manager QuickStart](../../live-service-management/gamemanager/quickstart.md). +- A [PlayFab developer account](https://developer.playfab.com). For information about creating a Title and finding TitleId, see [Game Manager QuickStart](../../live-service-management/gamemanager/quickstart.md). - [Node.js](https://nodejs.org/en/download/) - Node must be in your PATH environment variable. If you used the installer, it's probably set for you to the default location: C:/Program Files (x86)/nodejs/ @@ -26,7 +26,7 @@ Get started with the PlayFab client library for NodeJS to make your first PlayFa ## Setting up -The following commands work on Windows, MacOS, and Linux. +The following commands work on Windows, macOS, and Linux. 1. Create a new folder for your project {NodeProjLocation}: @@ -38,7 +38,7 @@ The following commands work on Windows, MacOS, and Linux. `npm install playfab-sdk --save` - (Keep this window open (we'll use it again later.) + (Keep this window open (you'll use it again later.) PlayFab installation complete! @@ -128,7 +128,7 @@ For the Node SDK, the functions in `PlayFabClientSDK` are named after the HTTP r - `var loginRequest = { TitleId: PlayFab.settings.titleId, CustomId: "GettingStartedGuide", CreateAccount: true };` - Most PlayFab API methods require input parameters, and those input parameters are packed into a request object. - Every API method requires a unique request object, with a mix of optional and mandatory parameters. - - For `LoginWithCustomIDRequest`, there is a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. `TitleId` is another mandatory parameter in JavaScript, and it must match `PlayFab.settings.titleId`. + - For `LoginWithCustomIDRequest`, there's a mandatory parameter of `CustomId`, which uniquely identifies a player and `CreateAccount`, which allows the creation of a new account with this call. `TitleId` is another mandatory parameter in JavaScript, and it must match `PlayFab.settings.titleId`. - For information about where to find `TitleId`, see [Game Manager QuickStart](../../live-service-management/gamemanager/quickstart.md). - In this case, `TitleId`, `customId`, and `CreateAccount` are from the Request Body of `LoginWithCustomID`. - `PlayFabClientSDK.LoginWithCustomID(loginRequest, LoginCallback);` @@ -142,7 +142,7 @@ For the Node SDK, the functions in `PlayFabClientSDK` are named after the HTTP r - `LoginCallback` contains two parameters: `error` and `result`. - When successful, `error` will be `null`, and the `result` object will contain the requested information, according to the API called. - This `result` contains some basic information about the player, but for most users, login is simply a mandatory step before calling other APIs. -- If error is not `null`, your API has failed. +- If error isn't `null`, your API has failed. @@ -151,13 +151,13 @@ For the Node SDK, the functions in `PlayFabClientSDK` are named after the HTTP r - API calls can fail for many reasons, and you should always attempt to handle failure. - The error object includes the error name, error code, and error message. Together, this information should be sufficient to diagnose your error. - Why API calls fail (In order of likelihood): - - `PlayFabSettings.TitleId` is not set. If you forget to set `TitleId` to your title, then nothing will work. - - Request parameters. If you have not provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. + - `PlayFabSettings.TitleId` isn't set. If you forget to set `TitleId` to your title, then nothing will work. + - Request parameters. If you haven't provided the correct or required information for a particular API call, then it will fail. See `error.errorMessage`, `error.errorDetails`, or `error.GenerateErrorReport()` for more info. - Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so any API call at any time can fail randomly, and then work immediately after. Going into a tunnel can disconnect you completely. - PlayFab server issue. As with all software, there can be issues. See our [release notes](../../release-notes/index.md) for updates. -- The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. +- The internet isn't 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. - Global API Method Error Codes can be found in [Global API Method Error Codes](../../api-references/global-api-method-error-codes.md). - - If you are having difficulty debugging an issue, and the information within the error information is not sufficient, please visit us on our [forums](https://community.playfab.com/index.html). + - If you're having difficulty debugging an issue, and the information within the error information isn't sufficient, visit us on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/sdks/playfab-cpp/quickstart-linux.md b/playfab-docs/sdks/playfab-cpp/quickstart-linux.md index dfb006332..25bcdb455 100644 --- a/playfab-docs/sdks/playfab-cpp/quickstart-linux.md +++ b/playfab-docs/sdks/playfab-cpp/quickstart-linux.md @@ -22,7 +22,7 @@ This quickstart was written using Ubuntu 18.04 LTS. ## Requirements -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). ## Linux C++ Project Setup diff --git a/playfab-docs/sdks/playfab-cpp/quickstart-windows.md b/playfab-docs/sdks/playfab-cpp/quickstart-windows.md index 2fd980d7f..24e701b19 100644 --- a/playfab-docs/sdks/playfab-cpp/quickstart-windows.md +++ b/playfab-docs/sdks/playfab-cpp/quickstart-windows.md @@ -23,7 +23,7 @@ This quickstart helps you make your first PlayFab API call in the using the Clie ## Requirements -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). - An installation of [Visual Studio](https://visualstudio.microsoft.com/). ## Windows C++ project setup diff --git a/playfab-docs/sdks/python/quickstart.md b/playfab-docs/sdks/python/quickstart.md index b4ae6a03a..c2f28358d 100644 --- a/playfab-docs/sdks/python/quickstart.md +++ b/playfab-docs/sdks/python/quickstart.md @@ -22,7 +22,7 @@ A native Python project can be used a few ways: ## Prerequisites -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). - [Python 3](https://www.python.org/downloads/) installed on your system. - You must also have the requests module installed. @@ -31,7 +31,7 @@ A native Python project can be used a few ways: > -If you are having difficulty debugging an issue, and the information provided the error information is not sufficient, please visit us on our [PlayFab forums](https://community.playfab.com/index.html). +If you're having difficulty debugging an issue, and the information provided the error information isn't sufficient, visit us on our [PlayFab forums](https://community.playfab.com/index.html). ## Python project setup @@ -41,7 +41,7 @@ If you are having difficulty debugging an issue, and the information provided th pip install playfab ``` -If `pip` is not in your path, use the following command instead. +If `pip` isn't in your path, use the following command instead. ```cmd python -m pip install playfab @@ -118,11 +118,11 @@ This optional last section describes each part of playfab_test.py in detail. - If the API call wasn't successful, failure will contain some error information and success will be `None`. - API calls can fail for many reasons, and you should always attempt to handle the failure. - Why API calls fail (In order of likelihood) - - `PlayFabSettings.TitleId` is not set. If you forget to set `titleId` to your title, then nothing will work. - - Request parameters. If you have not provided the correct or required information for a particular API call, then it will fail. + - `PlayFabSettings.TitleId` isn't set. If you forget to set `titleId` to your title, then nothing will work. + - Request parameters. If you haven't provided the correct or required information for a particular API call, then it will fail. - Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so any API call at any time can fail randomly, and then work immediately after. Going into a tunnel can disconnect you completely. - PlayFab server issue. As with all software, there can be issues. See our [release notes](../../release-notes/index.md) for updates. - - The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. + - The internet isn't 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server. - `PlayFabClientAPI.LoginWithCustomID` - Triggers the API call synchronously. When complete, the callback will be invoked. diff --git a/playfab-docs/sdks/sdkgenerator/quickstart.md b/playfab-docs/sdks/sdkgenerator/quickstart.md index d7d5b58a5..a47fc29e2 100644 --- a/playfab-docs/sdks/sdkgenerator/quickstart.md +++ b/playfab-docs/sdks/sdkgenerator/quickstart.md @@ -14,17 +14,17 @@ ms.localizationpriority: medium The SDK Generator is a node.js-based program that takes a JSON description of the PlayFab API, and uses it to generate out all the different SDKs that must be kept up to date. The SDK Generator project also contains the sources for all PlayFab SDKs on all platforms. If you want to make a change in an SDK, this is where the change has to go. -Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +Before you can call any PlayFab API, you must have a [PlayFab developer account](https://developer.playfab.com). ## Prerequisites 1. Any recent MS-Windows Operating System. 2. You must have Node.js installed:  - The location of node.exe must be in your PATH environment variable. Default: C:\Program Files (x86)\nodejs\ - - It is highly suggested that you install Node.js tools for Visual Studio: . + - It's highly suggested that you install Node.js tools for Visual Studio: . 3. `SdkGenerator` requires several PlayFab repositories, cloned to your local machine, as sibling folders to `SdkGenerator`. - `/SdkGenerator = ` (you're looking at it) - - `/sdks/` - For every SDK you want to generate, you should git-clone the PlayFab repository for that target into the "sdks" sub-folder first. In many cases, there are required files in the repo which are not generated. + - `/sdks/` - For every SDK you want to generate, you should git-clone the PlayFab repository for that target into the "sdks" subfolder first. In many cases, there are required files in the repo which aren't generated. 4. `SdkGenerator` can be configured to read from other PlayFab repositories, cloned to your local machine, as sibling folders to SdkGenerator. - `/API_Specs = ` @@ -72,13 +72,13 @@ Flags are optional, and can be used to generate console APIs. Setting up a new target in the `SdkGenerator` is fairly simple. This example has been added to the `SdkGenerator` for reference: [https://github.com/PlayFab/SDKGenerator/tree/master/targets/newTarget](https://github.com/PlayFab/SDKGenerator/tree/master/targets/newTarget). -- Add a new sub-folder in [SdkGenerator/Targets](https://github.com/PlayFab/SDKGenerator/tree/master/targets). +- Add a new subfolder in [SdkGenerator/Targets](https://github.com/PlayFab/SDKGenerator/tree/master/targets). - Add a "make.js" file to your new target. - Implement `makeClientAPI2`, `makeServerAPI`, and/or `makeCombinedAPI` in the file, as shown in the [NewTarget Example](https://github.com/PlayFab/SDKGenerator/blob/master/targets/newTarget/make.js). - - Optionally, you may use template files and source files, as described in the NewTarget example. -- Add a new bat-file to generate your sdk in [SdkGenerator/SDKBuildScripts](https://github.com/PlayFab/SDKGenerator/tree/master/SDKBuildScripts). + - Optionally, you could use template files and source files, as described in the NewTarget example. +- Add a new bat-file to generate your SDK in [SdkGenerator/SDKBuildScripts](https://github.com/PlayFab/SDKGenerator/tree/master/SDKBuildScripts). -PlayFab sometimes accepts submissions for new SDKs. This process is extensive, and it has to be integrated with our automated build and testing system. For more information contact us on the forums. +PlayFab sometimes accepts submissions for new SDKs. This process is extensive, and it has to be integrated with our automated build and testing system. For more information, contact us on the forums. ## Troubleshooting @@ -88,6 +88,6 @@ For a complete list of available APIs, check out the [API References](../../api We love to hear from our developer community! Do you have ideas on how we can make our products and services better? -Our Developer Success Team can assist with answering any questions as well as process any feedback you have about PlayFab services. +Our Developer Success Team can assist with answering any questions and process any feedback you have about PlayFab services. -[Forums, Support and Knowledge Base](https://community.playfab.com/) +[Forums, Support, and Knowledge Base](https://community.playfab.com/) diff --git a/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md b/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md index c0bd060e1..4bec0c56e 100644 --- a/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md +++ b/playfab-docs/sdks/unity3d/installing-unity3d-sdk.md @@ -22,7 +22,7 @@ You have two options when installing the PlayFab Unity 3D SDK: - Install the PlayFab Unity 3D SDK directly without using PlayFab Unity Editor Extensions. When you use this installation method, you configure your Unity Project directly by setting the property values in your code. -This content assumes you that you have a [PlayFab developer account](https://developer.playfab.com/en-us/sign-up) and an existing Unity Project. +This content assumes you that you have a [PlayFab developer account](https://developer.playfab.com) and an existing Unity Project. ## Download and install the SDK only diff --git a/playfab-docs/sdks/unity3d/quickstart.md b/playfab-docs/sdks/unity3d/quickstart.md index 656a2ded8..7204b670f 100644 --- a/playfab-docs/sdks/unity3d/quickstart.md +++ b/playfab-docs/sdks/unity3d/quickstart.md @@ -18,7 +18,7 @@ This quickstart helps you make your first PlayFab API call in the Unity engine. ## Requirements -- A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +- A [PlayFab developer account](https://developer.playfab.com). - An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for professional use, see [Download Unity](https://unity.com/download). > [!NOTE] > The PlayFab Unity SDK supports Unity Editor version 5.3 (released December 2015) and higher. diff --git a/playfab-docs/sdks/unreal/quickstart.md b/playfab-docs/sdks/unreal/quickstart.md index 6d9f9b9a4..f3c6cf5d5 100644 --- a/playfab-docs/sdks/unreal/quickstart.md +++ b/playfab-docs/sdks/unreal/quickstart.md @@ -24,7 +24,7 @@ You can use the PlayFab plugin for the Unreal Engine to manage LiveOps for your ## Prerequisites -* A [PlayFab developer account](https://developer.playfab.com/en-us/sign-up). +* A [PlayFab developer account](https://developer.playfab.com). * An installation of [Visual Studio](https://visualstudio.microsoft.com/downloads/) that is configured for Unreal Engine. For information about configuring Visual Studio, see [Setting Up Visual Studio for Unreal Engine](https://docs.unrealengine.com/en-US/Programming/Development/VisualStudioSetup/index.html). * An installation of the [Unreal Engine](https://www.unrealengine.com/download). For information about installing the Unreal Engine, see the [Unreal Engine installation guide](https://docs.unrealengine.com/4.27/en-US/Basics/Projects/Browser/). * An installation of the PlayFab Unreal plugin. You can install the Unreal plugin from the [Unreal Engine marketplace](https://www.unrealengine.com/marketplace/playfab-sdk). From d30c5b4962323d4ad9dbf4580a8fba56d8cca076 Mon Sep 17 00:00:00 2001 From: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Date: Tue, 24 Feb 2026 08:08:59 -0800 Subject: [PATCH 57/76] pf-review-edits-61134237-02-23-2026-01 (#2832) --- .../economy-monetization/economy-v2/catalog/bundles.md | 4 ++-- .../economy-monetization/economy-v2/inventory/etags.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/playfab-docs/economy-monetization/economy-v2/catalog/bundles.md b/playfab-docs/economy-monetization/economy-v2/catalog/bundles.md index d207d197a..30e570c98 100644 --- a/playfab-docs/economy-monetization/economy-v2/catalog/bundles.md +++ b/playfab-docs/economy-monetization/economy-v2/catalog/bundles.md @@ -18,7 +18,7 @@ Bundles allow you to group multiple items together into a single item. You can c ## Creating a Bundle -To create a bundle, you must first make sure you have published Catalog Items, Currency, or UGC that you want to be accessible/purchaseable in your game. You can follow the steps in the [Economy V2 Quickstart](../quickstart.md#step-3---publish-an-item-to-the-catalog) +To create a bundle, you must first make sure you have published Catalog Items, Currency, or user-generated content (UGC) that you want to be accessible/purchaseable in your game. You can follow the steps in the [Economy V2 Quickstart](../quickstart.md#step-3---publish-an-item-to-the-catalog) ### [GameManager](#tab/creating-bundle-game-manager) @@ -93,7 +93,7 @@ Response: ## Purchasing and Unpacking Bundles -When a player purchases a bundle, the bundle is **automatically unpacked** — the individual items referenced in the bundle are granted directly to the player's inventory. The bundle itself does not appear as an inventory item. For more details on how bundles interact with inventory, see [Bundles in Inventory](../inventory/index.md#bundles). +When a player purchases a bundle, the bundle is **automatically unpacked—the individual items referenced in the bundle are granted directly to the player's inventory. The bundle itself doesn't appear as an inventory item. For more details on how bundles interact with inventory, see [Bundles in Inventory](../inventory/index.md#bundles). Bundles are also the primary mechanism for linking real-money marketplace products to in-game items. Each bundle can be linked to one or more marketplace products using `AlternateIds`. For more information, see [Fraud Prevention Quickstart](../fraud-prevention/quickstart.md). diff --git a/playfab-docs/economy-monetization/economy-v2/inventory/etags.md b/playfab-docs/economy-monetization/economy-v2/inventory/etags.md index 18fcb72c4..fb659e488 100644 --- a/playfab-docs/economy-monetization/economy-v2/inventory/etags.md +++ b/playfab-docs/economy-monetization/economy-v2/inventory/etags.md @@ -18,7 +18,7 @@ ETags provide optimistic concurrency control for the PlayFab Inventory APIs. The ## How Inventory ETags work -Inventory read APIs such as `GetInventoryItems` return an `ETag` in the response body. This value represents the current version of the player's inventory collection. You can pass this value in subsequent write requests to ensure your changes don't conflict with other updates that may have occurred since you last read the inventory. +Inventory read APIs such as `GetInventoryItems` return an `ETag` in the response body. This value represents the current version of the player's inventory collection. You can pass this value in subsequent write requests to ensure your changes don't conflict with other updates that might have occurred since you last read the inventory. ### Example `GetInventoryItems` response with ETag @@ -44,8 +44,8 @@ Inventory read APIs such as `GetInventoryItems` return an `ETag` in the response Inventory write APIs support ETags through the following HTTP headers: -- **`X-PlayFab-Economy-If-Match`** — Pass a previously received `ETag` value. The request succeeds only if the inventory's current ETag matches. Use this when you need to guarantee that no other write has occurred since you last read the inventory. -- **`X-PlayFab-Economy-If-None-Match`** — Pass `*` as the value. The request succeeds only if the item does not already exist in the inventory. Useful for "create-only" scenarios. +- **`X-PlayFab-Economy-If-Match`**—Pass a previously received `ETag` value. The request succeeds only if the inventory's current ETag matches. Use this check when you need to guarantee that no other write has occurred since you last read the inventory. +- **`X-PlayFab-Economy-If-None-Match`**—Pass `*` as the value. The request succeeds only if the item doesn't already exist in the inventory. Useful for "create-only" scenarios. ## Supported APIs From dc2f660b2e4469a6c75b265e2c6e96d31731a656 Mon Sep 17 00:00:00 2001 From: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Date: Tue, 24 Feb 2026 14:39:33 -0800 Subject: [PATCH 58/76] PF ms.date edits (#2837) * pf-ms-date-edits-02-24-2026-01 * pf-ms-date-edits-02-24-2026-02 --- .../api-references/events/Addons/title-addon-changed.md | 2 +- .../api-references/events/CloudScript/cloudscript-executed.md | 2 +- .../api-references/events/Extension/export-completed.md | 2 +- .../api-references/events/PlayerIdentity/entity-deleted.md | 2 +- .../api-references/events/PlayerIdentity/logged-in-to-title.md | 2 +- .../events/PlayerIdentity/player-authenticated.md | 2 +- .../events/PlayerIdentity/player-custom-properties-changed.md | 2 +- .../events/PlayerIdentity/player-identity-link-added.md | 2 +- .../events/PlayerIdentity/player-identity-link-removed.md | 2 +- .../events/PlayerIdentity/player-updated-login-email.md | 2 +- .../events/PlayerProfile/access-policy-updated.md | 2 +- .../api-references/events/PlayerProfile/avatar-url-updated.md | 2 +- .../events/PlayerProfile/contact-email-updated.md | 2 +- .../api-references/events/PlayerProfile/files-changed.md | 2 +- .../api-references/events/PlayerProfile/language-updated.md | 2 +- .../api-references/events/PlayerProfile/objects-updated.md | 2 +- .../api-references/events/Telemetry/apikey-activated.md | 2 +- playfab-docs/api-references/events/Telemetry/apikey-created.md | 2 +- .../api-references/events/Telemetry/apikey-deactivated.md | 2 +- playfab-docs/api-references/events/Telemetry/apikey-deleted.md | 2 +- .../api-references/events/TitleCommunications/email-sent.md | 2 +- .../api-references/events/TitleCommunications/sent-email.md | 2 +- playfab-docs/api-references/events/TitleData/title-activated.md | 2 +- .../events/TitleData/title-data-override-deleted.md | 2 +- .../api-references/events/TitleData/title-data-updated.md | 2 +- .../api-references/events/TitleData/title-deactivated.md | 2 +- playfab-docs/api-references/events/data-types/artifact.md | 2 +- .../api-references/events/data-types/contactemaildetails.md | 2 +- playfab-docs/api-references/events/data-types/filedetails.md | 2 +- playfab-docs/api-references/events/data-types/objectdetails.md | 2 +- .../events/data-types/playercustompropertieschangeddetails.md | 2 +- playfab-docs/api-references/events/data-types/titledatatype.md | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) diff --git a/playfab-docs/api-references/events/Addons/title-addon-changed.md b/playfab-docs/api-references/events/Addons/title-addon-changed.md index eee0c4985..78f3a6b5a 100644 --- a/playfab-docs/api-references/events/Addons/title-addon-changed.md +++ b/playfab-docs/api-references/events/Addons/title-addon-changed.md @@ -3,7 +3,7 @@ title: title_addon_changed author: ronnyparedes description: title_addon_changed event. ms.author: ronnyparedes -ms.date: 06/02/2026 +ms.date: 02/06/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/CloudScript/cloudscript-executed.md b/playfab-docs/api-references/events/CloudScript/cloudscript-executed.md index 4da59a2c3..04ebaba06 100644 --- a/playfab-docs/api-references/events/CloudScript/cloudscript-executed.md +++ b/playfab-docs/api-references/events/CloudScript/cloudscript-executed.md @@ -3,7 +3,7 @@ title: cloudscript_executed author: ronnyparedes description: cloudscript_executed event. ms.author: ronnyparedes -ms.date: 06/02/2026 +ms.date: 02/06/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/Extension/export-completed.md b/playfab-docs/api-references/events/Extension/export-completed.md index 4dda3453e..f5b0ab4f2 100644 --- a/playfab-docs/api-references/events/Extension/export-completed.md +++ b/playfab-docs/api-references/events/Extension/export-completed.md @@ -3,7 +3,7 @@ title: export_completed author: ronnyparedes description: export_completed event. ms.author: ronnyparedes -ms.date: 09/02/2026 +ms.date: 02/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerIdentity/entity-deleted.md b/playfab-docs/api-references/events/PlayerIdentity/entity-deleted.md index 04fa4b9dd..e7972fcee 100644 --- a/playfab-docs/api-references/events/PlayerIdentity/entity-deleted.md +++ b/playfab-docs/api-references/events/PlayerIdentity/entity-deleted.md @@ -3,7 +3,7 @@ title: entity_deleted author: ronnyparedes description: entity_deleted event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerIdentity/logged-in-to-title.md b/playfab-docs/api-references/events/PlayerIdentity/logged-in-to-title.md index 0c5a894da..0d3d9b110 100644 --- a/playfab-docs/api-references/events/PlayerIdentity/logged-in-to-title.md +++ b/playfab-docs/api-references/events/PlayerIdentity/logged-in-to-title.md @@ -3,7 +3,7 @@ title: logged_in_to_title author: ronnyparedes description: logged_in_to_title event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-authenticated.md b/playfab-docs/api-references/events/PlayerIdentity/player-authenticated.md index ed6505531..62aabb8be 100644 --- a/playfab-docs/api-references/events/PlayerIdentity/player-authenticated.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-authenticated.md @@ -3,7 +3,7 @@ title: player_authenticated author: ronnyparedes description: player_authenticated event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-custom-properties-changed.md b/playfab-docs/api-references/events/PlayerIdentity/player-custom-properties-changed.md index f5a26d1a8..7668c2b6a 100644 --- a/playfab-docs/api-references/events/PlayerIdentity/player-custom-properties-changed.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-custom-properties-changed.md @@ -3,7 +3,7 @@ title: player_custom_properties_changed author: ronnyparedes description: player_custom_properties_changed event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-added.md b/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-added.md index fe585cf32..4a6d9c645 100644 --- a/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-added.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-added.md @@ -3,7 +3,7 @@ title: player_identity_link_added author: ronnyparedes description: player_identity_link_added event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-removed.md b/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-removed.md index fcd1951c2..6b23983f0 100644 --- a/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-removed.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-identity-link-removed.md @@ -3,7 +3,7 @@ title: player_identity_link_removed author: ronnyparedes description: player_identity_link_removed event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerIdentity/player-updated-login-email.md b/playfab-docs/api-references/events/PlayerIdentity/player-updated-login-email.md index d077c6207..58abb1238 100644 --- a/playfab-docs/api-references/events/PlayerIdentity/player-updated-login-email.md +++ b/playfab-docs/api-references/events/PlayerIdentity/player-updated-login-email.md @@ -3,7 +3,7 @@ title: player_updated_login_email author: ronnyparedes description: player_updated_login_email event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerProfile/access-policy-updated.md b/playfab-docs/api-references/events/PlayerProfile/access-policy-updated.md index 806fed0d4..10a9f331d 100644 --- a/playfab-docs/api-references/events/PlayerProfile/access-policy-updated.md +++ b/playfab-docs/api-references/events/PlayerProfile/access-policy-updated.md @@ -3,7 +3,7 @@ title: access_policy_updated author: ronnyparedes description: access_policy_updated event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerProfile/avatar-url-updated.md b/playfab-docs/api-references/events/PlayerProfile/avatar-url-updated.md index 02c20c164..111cde07b 100644 --- a/playfab-docs/api-references/events/PlayerProfile/avatar-url-updated.md +++ b/playfab-docs/api-references/events/PlayerProfile/avatar-url-updated.md @@ -3,7 +3,7 @@ title: avatar_url_updated author: ronnyparedes description: avatar_url_updated event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerProfile/contact-email-updated.md b/playfab-docs/api-references/events/PlayerProfile/contact-email-updated.md index 544807b2e..1b0ea3278 100644 --- a/playfab-docs/api-references/events/PlayerProfile/contact-email-updated.md +++ b/playfab-docs/api-references/events/PlayerProfile/contact-email-updated.md @@ -3,7 +3,7 @@ title: contact_email_updated author: ronnyparedes description: contact_email_updated event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerProfile/files-changed.md b/playfab-docs/api-references/events/PlayerProfile/files-changed.md index 95464cf14..6f3c947ee 100644 --- a/playfab-docs/api-references/events/PlayerProfile/files-changed.md +++ b/playfab-docs/api-references/events/PlayerProfile/files-changed.md @@ -3,7 +3,7 @@ title: files_changed author: ronnyparedes description: files_changed event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerProfile/language-updated.md b/playfab-docs/api-references/events/PlayerProfile/language-updated.md index 6fedefc46..08e1b8595 100644 --- a/playfab-docs/api-references/events/PlayerProfile/language-updated.md +++ b/playfab-docs/api-references/events/PlayerProfile/language-updated.md @@ -3,7 +3,7 @@ title: language_updated author: ronnyparedes description: language_updated event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/PlayerProfile/objects-updated.md b/playfab-docs/api-references/events/PlayerProfile/objects-updated.md index 2df40b4a9..94f8ee526 100644 --- a/playfab-docs/api-references/events/PlayerProfile/objects-updated.md +++ b/playfab-docs/api-references/events/PlayerProfile/objects-updated.md @@ -3,7 +3,7 @@ title: objects_updated author: ronnyparedes description: objects_updated event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/Telemetry/apikey-activated.md b/playfab-docs/api-references/events/Telemetry/apikey-activated.md index e617ae962..4405bc510 100644 --- a/playfab-docs/api-references/events/Telemetry/apikey-activated.md +++ b/playfab-docs/api-references/events/Telemetry/apikey-activated.md @@ -3,7 +3,7 @@ title: apikey_activated author: ronnyparedes description: apikey_activated event. ms.author: ronnyparedes -ms.date: 09/02/2026 +ms.date: 02/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/Telemetry/apikey-created.md b/playfab-docs/api-references/events/Telemetry/apikey-created.md index 17d6314c4..e247557b4 100644 --- a/playfab-docs/api-references/events/Telemetry/apikey-created.md +++ b/playfab-docs/api-references/events/Telemetry/apikey-created.md @@ -3,7 +3,7 @@ title: apikey_created author: ronnyparedes description: apikey_created event. ms.author: ronnyparedes -ms.date: 09/02/2026 +ms.date: 02/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/Telemetry/apikey-deactivated.md b/playfab-docs/api-references/events/Telemetry/apikey-deactivated.md index 50e43ecbe..63ab66a8a 100644 --- a/playfab-docs/api-references/events/Telemetry/apikey-deactivated.md +++ b/playfab-docs/api-references/events/Telemetry/apikey-deactivated.md @@ -3,7 +3,7 @@ title: apikey_deactivated author: ronnyparedes description: apikey_deactivated event. ms.author: ronnyparedes -ms.date: 09/02/2026 +ms.date: 02/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/Telemetry/apikey-deleted.md b/playfab-docs/api-references/events/Telemetry/apikey-deleted.md index 100decc64..1f110fd17 100644 --- a/playfab-docs/api-references/events/Telemetry/apikey-deleted.md +++ b/playfab-docs/api-references/events/Telemetry/apikey-deleted.md @@ -3,7 +3,7 @@ title: apikey_deleted author: ronnyparedes description: apikey_deleted event. ms.author: ronnyparedes -ms.date: 09/02/2026 +ms.date: 02/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/TitleCommunications/email-sent.md b/playfab-docs/api-references/events/TitleCommunications/email-sent.md index 712303ea9..a9765a98b 100644 --- a/playfab-docs/api-references/events/TitleCommunications/email-sent.md +++ b/playfab-docs/api-references/events/TitleCommunications/email-sent.md @@ -3,7 +3,7 @@ title: email_sent author: ronnyparedes description: email_sent event. ms.author: ronnyparedes -ms.date: 09/02/2026 +ms.date: 02/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/TitleCommunications/sent-email.md b/playfab-docs/api-references/events/TitleCommunications/sent-email.md index bb4734538..d870e93f2 100644 --- a/playfab-docs/api-references/events/TitleCommunications/sent-email.md +++ b/playfab-docs/api-references/events/TitleCommunications/sent-email.md @@ -3,7 +3,7 @@ title: sent_email author: ronnyparedes description: sent_email event. ms.author: ronnyparedes -ms.date: 09/02/2026 +ms.date: 02/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/TitleData/title-activated.md b/playfab-docs/api-references/events/TitleData/title-activated.md index 7c2ae0e3d..ba66b33ba 100644 --- a/playfab-docs/api-references/events/TitleData/title-activated.md +++ b/playfab-docs/api-references/events/TitleData/title-activated.md @@ -3,7 +3,7 @@ title: title_activated author: ronnyparedes description: title_activated event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/TitleData/title-data-override-deleted.md b/playfab-docs/api-references/events/TitleData/title-data-override-deleted.md index b2e80bb9f..ffcb98d7b 100644 --- a/playfab-docs/api-references/events/TitleData/title-data-override-deleted.md +++ b/playfab-docs/api-references/events/TitleData/title-data-override-deleted.md @@ -3,7 +3,7 @@ title: title_data_override_deleted author: ronnyparedes description: title_data_override_deleted event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/TitleData/title-data-updated.md b/playfab-docs/api-references/events/TitleData/title-data-updated.md index 2e638de98..2d212f190 100644 --- a/playfab-docs/api-references/events/TitleData/title-data-updated.md +++ b/playfab-docs/api-references/events/TitleData/title-data-updated.md @@ -3,7 +3,7 @@ title: title_data_updated author: ronnyparedes description: title_data_updated event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/TitleData/title-deactivated.md b/playfab-docs/api-references/events/TitleData/title-deactivated.md index bfc97b320..2a76c8673 100644 --- a/playfab-docs/api-references/events/TitleData/title-deactivated.md +++ b/playfab-docs/api-references/events/TitleData/title-deactivated.md @@ -3,7 +3,7 @@ title: title_deactivated author: ronnyparedes description: title_deactivated event. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/data-types/artifact.md b/playfab-docs/api-references/events/data-types/artifact.md index 6c0f3fe05..b88edde1e 100644 --- a/playfab-docs/api-references/events/data-types/artifact.md +++ b/playfab-docs/api-references/events/data-types/artifact.md @@ -3,7 +3,7 @@ title: Artifact author: ronnyparedes description: Artifact data type. ms.author: ronnyparedes -ms.date: 09/02/2026 +ms.date: 02/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/data-types/contactemaildetails.md b/playfab-docs/api-references/events/data-types/contactemaildetails.md index 2b74037f3..a7411677b 100644 --- a/playfab-docs/api-references/events/data-types/contactemaildetails.md +++ b/playfab-docs/api-references/events/data-types/contactemaildetails.md @@ -3,7 +3,7 @@ title: ContactEmailDetails author: ronnyparedes description: ContactEmailDetails data type. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/data-types/filedetails.md b/playfab-docs/api-references/events/data-types/filedetails.md index 95139b6a2..4e8bce7ae 100644 --- a/playfab-docs/api-references/events/data-types/filedetails.md +++ b/playfab-docs/api-references/events/data-types/filedetails.md @@ -3,7 +3,7 @@ title: FileDetails author: ronnyparedes description: FileDetails data type. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/data-types/objectdetails.md b/playfab-docs/api-references/events/data-types/objectdetails.md index 8f3a7ea14..776abb60e 100644 --- a/playfab-docs/api-references/events/data-types/objectdetails.md +++ b/playfab-docs/api-references/events/data-types/objectdetails.md @@ -3,7 +3,7 @@ title: ObjectDetails author: ronnyparedes description: ObjectDetails data type. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/data-types/playercustompropertieschangeddetails.md b/playfab-docs/api-references/events/data-types/playercustompropertieschangeddetails.md index 12fa66db5..a5f08c22a 100644 --- a/playfab-docs/api-references/events/data-types/playercustompropertieschangeddetails.md +++ b/playfab-docs/api-references/events/data-types/playercustompropertieschangeddetails.md @@ -3,7 +3,7 @@ title: PlayerCustomPropertiesChangedDetails author: ronnyparedes description: PlayerCustomPropertiesChangedDetails data type. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events diff --git a/playfab-docs/api-references/events/data-types/titledatatype.md b/playfab-docs/api-references/events/data-types/titledatatype.md index 5f95ce9d9..c364a92e3 100644 --- a/playfab-docs/api-references/events/data-types/titledatatype.md +++ b/playfab-docs/api-references/events/data-types/titledatatype.md @@ -3,7 +3,7 @@ title: TitleDataType author: ronnyparedes description: TitleDataType data type. ms.author: ronnyparedes -ms.date: 12/02/2026 +ms.date: 02/12/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events From ff63123415d4c1583f7617d10b57ef2a690b4107 Mon Sep 17 00:00:00 2001 From: ronnyparedesc <113482725+ronnyparedesc@users.noreply.github.com> Date: Tue, 24 Feb 2026 21:45:57 -0800 Subject: [PATCH 59/76] PlayStream event documentation update Party (#2793) * Add Party PS events * PlayStream event documentation: fix Party events (#2817) * Adding missing event and removing one * Adding missing events * Revert "Adding missing events" This reverts commit 2844ac6f6b4f0fa54c79fc2a6ca5ecedc8afb87a. * pf-review-edits-pr-2813-02-17-2026-01 --------- Co-authored-by: Raul Gomez Rodriguez Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Removing internal events * Addressing PR Feedback * Updating author and ms.author * Cleaning up unrelated Networking changes in index.md * Adding events to toc.yml file * Removing unwanted events * Removing extra space --------- Co-authored-by: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --- .../client-authentication-completed.md | 32 ++++++++++++++ .../Networking/client-connected-to-network.md | 35 ++++++++++++++++ .../client-initialization-completed.md | 26 ++++++++++++ .../Networking/client-network-created.md | 42 +++++++++++++++++++ .../Networking/client-network-destroyed.md | 33 +++++++++++++++ .../client-network-information-received.md | 35 ++++++++++++++++ .../Networking/client-request-failed.md | 31 ++++++++++++++ .../Networking/data-received-by-clients.md | 27 ++++++++++++ .../events/Networking/data-sent-by-clients.md | 27 ++++++++++++ .../moderation-service-request-count.md | 27 ++++++++++++ .../player-disconnected-from-network.md | 28 +++++++++++++ .../unity-client-initialization-completed.md | 34 +++++++++++++++ .../unreal-client-initialization-completed.md | 37 ++++++++++++++++ playfab-docs/api-references/events/index.md | 41 ++++++++++++++++++ playfab-docs/api-references/toc.yml | 28 ++++++++++++- 15 files changed, 482 insertions(+), 1 deletion(-) create mode 100644 playfab-docs/api-references/events/Networking/client-authentication-completed.md create mode 100644 playfab-docs/api-references/events/Networking/client-connected-to-network.md create mode 100644 playfab-docs/api-references/events/Networking/client-initialization-completed.md create mode 100644 playfab-docs/api-references/events/Networking/client-network-created.md create mode 100644 playfab-docs/api-references/events/Networking/client-network-destroyed.md create mode 100644 playfab-docs/api-references/events/Networking/client-network-information-received.md create mode 100644 playfab-docs/api-references/events/Networking/client-request-failed.md create mode 100644 playfab-docs/api-references/events/Networking/data-received-by-clients.md create mode 100644 playfab-docs/api-references/events/Networking/data-sent-by-clients.md create mode 100644 playfab-docs/api-references/events/Networking/moderation-service-request-count.md create mode 100644 playfab-docs/api-references/events/Networking/player-disconnected-from-network.md create mode 100644 playfab-docs/api-references/events/Networking/unity-client-initialization-completed.md create mode 100644 playfab-docs/api-references/events/Networking/unreal-client-initialization-completed.md diff --git a/playfab-docs/api-references/events/Networking/client-authentication-completed.md b/playfab-docs/api-references/events/Networking/client-authentication-completed.md new file mode 100644 index 000000000..d990a6cc1 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-authentication-completed.md @@ -0,0 +1,32 @@ +--- +title: client_authentication_completed +author: raulalbertog +description: client_authentication_completed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_authentication_completed + +This event is triggered when client authentication is completed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier at the time of this event.| +|AuthDurationInMs|uint32|The duration of the isolated authentication operation in milliseconds.| +|TotalDurationInMs|uint32|The duration of the authentication operation and all associated operations queued before it in milliseconds.| +|LocalConnectionId|uint32|A local identifier to disambiguate multiple connections to the same network from a single client.| +|Result|int32|The PartyStateChangeResult of the operation.| +|ResultMessage|String|A human-readable representation of the Result value.| +|ErrorDetail|uint32|The PartyError error detail code.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-connected-to-network.md b/playfab-docs/api-references/events/Networking/client-connected-to-network.md new file mode 100644 index 000000000..e43473039 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-connected-to-network.md @@ -0,0 +1,35 @@ +--- +title: client_connected_to_network +author: raulalbertog +description: client_connected_to_network event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_connected_to_network + +This event is triggered when a client connects to a network. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier.| +|RegionName|String|The region name associated with the underlying relay for the network.| +|HostName|String|The hostname of the relay the client is connecting to.| +|Port|uint16|The port the client is connecting to.| +|ConnectDurationInMs|uint32|The duration of the isolated connection operation in milliseconds.| +|TotalDurationInMs|uint32|The duration of the connection operation and all associated operations queued before it in milliseconds.| +|LocalConnectionId|uint32|A local identifier to disambiguate multiple connections to the same network from a single client.| +|Result|int32|The PartyStateChangeResult of the operation.| +|ResultMessage|String|A human-readable representation of the Result value.| +|ErrorDetail|uint32|The PartyError error detail code.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-initialization-completed.md b/playfab-docs/api-references/events/Networking/client-initialization-completed.md new file mode 100644 index 000000000..d8baf8f87 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-initialization-completed.md @@ -0,0 +1,26 @@ +--- +title: client_initialization_completed +author: raulalbertog +description: client_initialization_completed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_initialization_completed + +This event is triggered when client initialization is completed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|BuildId|String|The identifier of the build that produced this binary.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-network-created.md b/playfab-docs/api-references/events/Networking/client-network-created.md new file mode 100644 index 000000000..a024cc84a --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-network-created.md @@ -0,0 +1,42 @@ +--- +title: client_network_created +author: raulalbertog +description: client_network_created event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_network_created + +This event is triggered when a client network is created. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier.| +|RegionName|String|The region name associated with the newly created network. Empty if the creation failed.| +|ServerId|String|The ServerId field from the PlayFab RequestPartyResponse.| +|VmId|String|The VmId field from the PlayFab RequestPartyResponse.| +|DurationInMs|uint32|The duration of this request in milliseconds.| +|Result|int32|The PartyStateChangeResult of the operation.| +|ResultMessage|String|A human-readable representation of the Result value.| +|ErrorDetail|uint32|The PartyError error detail code.| +|RegionCount|uint32|The count of regions specified when creating the network.| +|MaxUserCount|uint32|The maximum user count specified in the network configuration.| +|MaxDeviceCount|uint32|The maximum device count specified in the network configuration.| +|MaxUsersPerDeviceCount|uint32|The maximum users per device count specified in the network configuration.| +|MaxDevicesPerUserCount|uint32|The maximum devices per user count specified in the network configuration.| +|MaxEndpointsPerDeviceCount|uint32|The maximum endpoints per device count specified in the network configuration.| +|DirectPeerConnectivityOptions|int32|The direct peer connectivity options specified when creating the network.| +|RequestedRelayVersion|String|The requested relay protocol version.| +|RequestedRelayBuildAliasId|String|The requested relay build alias ID.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-network-destroyed.md b/playfab-docs/api-references/events/Networking/client-network-destroyed.md new file mode 100644 index 000000000..342af177a --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-network-destroyed.md @@ -0,0 +1,33 @@ +--- +title: client_network_destroyed +author: raulalbertog +description: client_network_destroyed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_network_destroyed + +This event is triggered when a client network is destroyed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier at the time it was destroyed.| +|RegionName|String|The region name associated with the underlying relay for the network.| +|HostName|String|The relay's hostname.| +|Port|uint16|The relay's port.| +|LocalConnectionId|uint32|A local identifier to disambiguate multiple connections to the same network from a single client.| +|Reason|int32|The PartyDestroyedReason that the network was destroyed.| +|ReasonMessage|String|A human-readable representation of the Reason value.| +|ErrorDetail|uint32|The PartyError error detail code.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-network-information-received.md b/playfab-docs/api-references/events/Networking/client-network-information-received.md new file mode 100644 index 000000000..db236fe29 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-network-information-received.md @@ -0,0 +1,35 @@ +--- +title: client_network_information_received +author: raulalbertog +description: client_network_information_received event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_network_information_received + +This event is triggered when client network information is received. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier.| +|NetworkInformationDurationInMs|uint32|The duration of the connection operation up to the point of receiving the network information, in milliseconds.| +|TotalDurationInMs|uint32|The duration of the connection operation, receiving the network information, and all associated operations queued before it in milliseconds.| +|MaxUserCount|uint32|The maximum user count specified in the network configuration.| +|MaxDeviceCount|uint32|The maximum device count specified in the network configuration.| +|MaxUsersPerDeviceCount|uint32|The maximum users per device count specified in the network configuration.| +|MaxDevicesPerUserCount|uint32|The maximum devices per user count specified in the network configuration.| +|MaxEndpointsPerDeviceCount|uint32|The maximum endpoints per device count specified in the network configuration.| +|NetworkDirectPeerConnectivityOptions|int32|The direct peer connectivity options specified in the network configuration.| +|LocalDeviceDirectPeerConnectivityOptions|int32|The direct peer connectivity options specified by the local device when connecting to the network.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-request-failed.md b/playfab-docs/api-references/events/Networking/client-request-failed.md new file mode 100644 index 000000000..794f89704 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-request-failed.md @@ -0,0 +1,31 @@ +--- +title: client_request_failed +author: raulalbertog +description: client_request_failed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_request_failed + +This event is triggered when a client request fails. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|RequestType|String|The type of the request that failed.| +|HttpStatusCode|int32|The HTTP status code of the failed request.| +|HttpStatusString|String|The HTTP status string of the failed request.| +|PlayFabErrorCode|int32|The PlayFab error code.| +|ErrorName|String|The PlayFab error name.| +|ErrorMessage|String|The PlayFab error message.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/data-received-by-clients.md b/playfab-docs/api-references/events/Networking/data-received-by-clients.md new file mode 100644 index 000000000..eb1ee2736 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/data-received-by-clients.md @@ -0,0 +1,27 @@ +--- +title: data_received_by_clients +author: raulalbertog +description: data_received_by_clients event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# data_received_by_clients + +This event is triggered when data is received by clients. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|LoginIdentityProvider|String|The identity provider used for login.| +|RegionName|String|The region name associated with the relay.| +|DataSizeInBytes|uint64|The total data size in bytes received by clients from the cloud service.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/data-sent-by-clients.md b/playfab-docs/api-references/events/Networking/data-sent-by-clients.md new file mode 100644 index 000000000..fd55f6da5 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/data-sent-by-clients.md @@ -0,0 +1,27 @@ +--- +title: data_sent_by_clients +author: raulalbertog +description: data_sent_by_clients event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# data_sent_by_clients + +This event is triggered when data is sent by clients. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|LoginIdentityProvider|String|The identity provider used for login.| +|RegionName|String|The region name associated with the relay.| +|DataSizeInBytes|uint64|The total data size in bytes sent by clients to the cloud service.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/moderation-service-request-count.md b/playfab-docs/api-references/events/Networking/moderation-service-request-count.md new file mode 100644 index 000000000..3ae8d17cf --- /dev/null +++ b/playfab-docs/api-references/events/Networking/moderation-service-request-count.md @@ -0,0 +1,27 @@ +--- +title: moderation_service_request_count +author: raulalbertog +description: moderation_service_request_count event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# moderation_service_request_count + +This event is triggered when moderation service request count is reported. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|LoginIdentityProvider|String|The identity provider used for login.| +|RegionName|String|The region name associated with the relay.| +|DataSizeInBytes|uint64|The total count of moderation service requests.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/player-disconnected-from-network.md b/playfab-docs/api-references/events/Networking/player-disconnected-from-network.md new file mode 100644 index 000000000..8c9267502 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/player-disconnected-from-network.md @@ -0,0 +1,28 @@ +--- +title: player_disconnected_from_network +author: raulalbertog +description: player_disconnected_from_network event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_disconnected_from_network + +This event is triggered when a player disconnects from a network. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|LoginIdentityProvider|String|The identity provider used for login.| +|RegionName|String|The region name associated with the relay.| +|ChatDurationInMs|uint64|The total duration of chat time in milliseconds.| +|ConnectedDurationInMs|uint64|The total duration the player was connected to the network in milliseconds.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/unity-client-initialization-completed.md b/playfab-docs/api-references/events/Networking/unity-client-initialization-completed.md new file mode 100644 index 000000000..084656ea5 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/unity-client-initialization-completed.md @@ -0,0 +1,34 @@ +--- +title: unity_client_initialization_completed +author: raulalbertog +description: unity_client_initialization_completed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# unity_client_initialization_completed + +This event is triggered when Unity client initialization is completed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|A unique identifier for this game session.| +|PartyVersion|String|The version of the Party native library.| +|PartyUnityVersion|String|The version of the Party Unity SDK.| +|UnityVersion|String|The version of the Unity engine.| +|OSName|String|The name of the operating system.| +|DeviceMake|String|The device manufacturer name.| +|DeviceModel|String|The device model name.| +|Platform|String|The Unity runtime platform.| +|AppName|String|The application product name.| +|AppVersion|String|The application version.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/unreal-client-initialization-completed.md b/playfab-docs/api-references/events/Networking/unreal-client-initialization-completed.md new file mode 100644 index 000000000..84fcbe122 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/unreal-client-initialization-completed.md @@ -0,0 +1,37 @@ +--- +title: unreal_client_initialization_completed +author: raulalbertog +description: unreal_client_initialization_completed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# unreal_client_initialization_completed + +This event is triggered when Unreal client initialization is completed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|A unique identifier for this game session.| +|PartyVersion|String|The version of the Party native library.| +|UnrealEngineVersion|String|The version of the Unreal Engine.| +|PlatformSDKVersion|String|The version of the platform SDK.| +|OSSPlayFabVersion|String|The version of the OnlineSubsystemPlayFab plugin.| +|TitleID|String|The PlayFab title ID.| +|OSName|String|The name of the operating system.| +|OSVersion|String|The version of the operating system.| +|DeviceMake|String|The device manufacturer name.| +|DeviceModel|String|The device model name.| +|PlatformName|String|The name of the platform.| +|AppName|String|The application name.| +|AppVersion|String|The application version.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 51dea43a3..818094697 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -399,6 +399,47 @@ Each event type has a set of properties that are included as part of event's dat - [gamesave_version_marked_known_good](GameSave/gamesave-version-marked-known-good.md) This event is triggered when a game save version is marked as known good. +## Networking + +- [client_authentication_completed](Networking/client-authentication-completed.md) + This event is triggered when client authentication is completed. + +- [client_connected_to_network](Networking/client-connected-to-network.md) + This event is triggered when a client connects to a network. + +- [client_initialization_completed](Networking/client-initialization-completed.md) + This event is triggered when client initialization is completed. + +- [client_network_created](Networking/client-network-created.md) + This event is triggered when a client network is created. + +- [client_network_destroyed](Networking/client-network-destroyed.md) + This event is triggered when a client network is destroyed. + +- [client_network_information_received](Networking/client-network-information-received.md) + This event is triggered when client network information is received. + +- [client_request_failed](Networking/client-request-failed.md) + This event is triggered when a client request fails. + +- [data_received_by_clients](Networking/data-received-by-clients.md) + This event is triggered when data is received by clients. + +- [data_sent_by_clients](Networking/data-sent-by-clients.md) + This event is triggered when data is sent by clients. + +- [moderation_service_request_count](Networking/moderation-service-request-count.md) + This event is triggered when moderation service request count is reported. + +- [player_disconnected_from_network](Networking/player-disconnected-from-network.md) + This event is triggered when a player disconnects from a network. + +- [unity_client_initialization_completed](Networking/unity-client-initialization-completed.md) + This event is triggered when Unity client initialization is completed. + +- [unreal_client_initialization_completed](Networking/unreal-client-initialization-completed.md) + This event is triggered when Unreal client initialization is completed. + ## Partner - [display_name_filtered](Partner/display-name-filtered.md) diff --git a/playfab-docs/api-references/toc.yml b/playfab-docs/api-references/toc.yml index 38e494193..36dc3f475 100644 --- a/playfab-docs/api-references/toc.yml +++ b/playfab-docs/api-references/toc.yml @@ -442,6 +442,32 @@ href: events/Leaderboards/character-statistic-changed.md - name: character_statistic_deleted href: events/Leaderboards/character-statistic-deleted.md + - name: client_authentication_completed + href: events/Networking/client-authentication-completed.md + - name: client_connected_to_network + href: events/Networking/client-connected-to-network.md + - name: client_initialization_completed + href: events/Networking/client-initialization-completed.md + - name: client_network_created + href: events/Networking/client-network-created.md + - name: client_network_destroyed + href: events/Networking/client-network-destroyed.md + - name: client_network_information_received + href: events/Networking/client-network-information-received.md + - name: client_request_failed + href: events/Networking/client-request-failed.md + - name: data_received_by_clients + href: events/Networking/data-received-by-clients.md + - name: data_sent_by_clients + href: events/Networking/data-sent-by-clients.md + - name: moderation_service_request_count + href: events/Networking/moderation-service-request-count.md + - name: player_disconnected_from_network + href: events/Networking/player-disconnected-from-network.md + - name: unity_client_initialization_completed + href: events/Networking/unity-client-initialization-completed.md + - name: unreal_client_initialization_completed + href: events/Networking/unreal-client-initialization-completed.md - name: entity_rank_on_leaderboard_version_ended href: events/Leaderboards/entity-rank-on-leaderboard-version-ended.md - name: leaderboard_version_ended @@ -461,4 +487,4 @@ - name: Global API method error codes href: global-api-method-error-codes.md - name: HTTP response status codes - href: http-response-status-codes.md + href: http-response-status-codes.md \ No newline at end of file From c27ef2f50aa22a6fcb4b19e181fd96e4f4d6ea99 Mon Sep 17 00:00:00 2001 From: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Date: Wed, 25 Feb 2026 09:18:45 -0800 Subject: [PATCH 60/76] pf-review-edits-61014764-02-24-2026-01 (#2836) --- .../title-permission-policy-changed.md | 2 +- .../CloudScript/entity-executed-cloud-script.md | 2 +- .../CloudScript/player-executed-cloudscript.md | 2 +- .../events/CloudScript/title-added-cloudscript.md | 2 +- playfab-docs/api-references/events/index.md | 14 +++++++------- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md b/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md index 0434064f5..f287f2d6e 100644 --- a/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md +++ b/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # title_permission_policy_changed -This event is triggered when an update occurs to a a title's permission policies. +This event is triggered when an update occurs to a title's permission policies. ## Properties diff --git a/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md b/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md index 1e8ad14aa..d11f611b6 100644 --- a/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md +++ b/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md @@ -18,7 +18,7 @@ This event is optionally triggered when a CloudScript function is executed by ca |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that is useful for debugging.| +|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that's useful for debugging.| |EntityChain|String|The chain of ownership for this entity.| |EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |FunctionName|String|Name of the CloudScript function that was called.| diff --git a/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md b/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md index 4c526f032..08579b360 100644 --- a/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md +++ b/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md @@ -18,7 +18,7 @@ This event is optionally triggered when a CloudScript function is executed, eith |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that is useful for debugging.| +|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that's useful for debugging.| |FunctionName|String|Name of the CloudScript function that was called.| |TitleId|String|The ID of the title to which this player event applies.| diff --git a/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md b/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md index bc7b41782..18f22de08 100644 --- a/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md +++ b/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md @@ -21,7 +21,7 @@ This event is triggered when new CloudScript is uploaded to PlayFab. |DeveloperId|String|| |Published|Boolean|Whether the CloudScript that was uploaded is live.| |Revision|int32|Revision number of the CloudScript file that was added.| -|ScriptNames|[]|Names of the individual script files modified. Currently this is just 'CloudScript.js' but later we will support multiple files.| +|ScriptNames|[]|Names of the individual script files modified. Currently this is just 'CloudScript.js' but later we'll support multiple files.| |UserId|String|| |Version|int32|Version number of the CloudScript file that was added.| diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 818094697..116d89d00 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -14,7 +14,7 @@ ms.localizationpriority: medium These are the built-in PlayStream events which are automatically generated by PlayFab Game Services APIs and written to the event pipeline. In addition to these events, you can create your own custom events using the [WriteEvents](xref:titleid.playfabapi.com.events.playstreamevents.writeevents) API. -Each event type has a set of properties that are included as part of event's data wherever it is sent. You can view these properties and build rules for triggering actions based on their values in the PlayStream tab of the Game Manager. +Each event type has a set of properties that are included as part of event's data wherever it's sent. You can view these properties and build rules for triggering actions based on their values in the PlayStream tab of the Game Manager. ## AdPlacement @@ -28,7 +28,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a player opens an ad. - [player_ad_rewarded](AdPlacement/player-ad-rewarded.md) - This event is triggered when a player recieves an ad reward. + This event is triggered when a player receives an ad reward. - [player_ad_started](AdPlacement/player-ad-started.md) This event is triggered when a player starts an ad. @@ -44,7 +44,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when an API Features setting is changed for the title. - [title_permission_policy_changed](ApiAccessPolicy/title-permission-policy-changed.md) - This event is triggered when an update occurs to a a title's permission policies. + This event is triggered when an update occurs to a title's permission policies. ## CloudScript @@ -98,7 +98,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a task is deleted. - [title_exceeded_limit](Extension/title-exceeded-limit.md) - This event is triggererd when a title exceeds a service limit and receives an error. + This event is triggered when a title exceeds a service limit and receives an error. - [title_limit_changed](Extension/title-limit-changed.md) This event is triggered when a title changes a service limit. @@ -325,7 +325,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when an item moderation state is changed. - [item_publish_requested](catalogv2/item-publish-requested.md) - This event is triggered when an publishing is started. + This event is triggered when publishing is started. - [item_purchased](catalogv2/item-purchased.md) This event is triggered when an item is purchased. @@ -340,7 +340,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a review is reported. - [reviews_takedown_requested](catalogv2/reviews-takedown-requested.md) - Event trigged when a takedown of reviews is requested. + This event is triggered when a takedown of reviews is requested. ## Character @@ -446,7 +446,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a display name is filtered by community sift. - [player_display_name_filtered](Partner/player-display-name-filtered.md) - This event is triggered when a display name is filtered by community sift only if there is an associated player EntityId for the event. + This event is triggered when a display name is filtered by community sift only if there's an associated player EntityId for the event. - [player_photon_session_authenticated](Partner/player-photon-session-authenticated.md) This event is triggered when a player connects to a Photon Cloud application and authenticates with PlayFab using Photon custom authentication. From 61fad44efeadb8853b1729a3d0f274868821a4cd Mon Sep 17 00:00:00 2001 From: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:13:43 -0600 Subject: [PATCH 61/76] Rename-playfab-remove-azure (#2810) * Remove all instances of "Azure PlayFab" in preference of "PlayFab" * Correcting all branding mismatches of "Playfab" to "PlayFab" * Further corrections on branding * Update playfab-docs/multiplayer/servers/directly-debugging-game-servers.md Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * pf-review-edits-pr-2810-02-19-2026-01 * pf-review-edits-pr-2810-02-19-2026-02 * pf-review-edits-pr-2810-02-19-2026-03 * Fix formatting in PlayFab fundamentals summary and description Acrolinx --------- Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --- playfab-docs/breadcrumb/toc.yml | 64 +++++---- playfab-docs/community/index.yml | 2 +- playfab-docs/community/leaderboards/index.md | 8 +- .../leaderboards/leaderboards-cloudscript.md | 22 +-- .../leaderboards-linked-to-stats.md | 2 +- .../export-data/data-connection-azure-blob.md | 40 +++--- playfab-docs/data-analytics/index.yml | 2 +- ...etting-started-with-data-explorer-basic.md | 2 +- .../legacy/insights/best-practices.md | 2 +- .../legacy/insights/overview.md | 30 ++--- .../legacy/insights/performance-retention.md | 2 +- .../legacy/insights/scheduled-scaling.md | 2 +- .../economy-monetization/economy-v2/faq.md | 2 +- .../economy-v2/fraud-prevention/quickstart.md | 4 +- .../marketplace-integrations/google.md | 2 +- .../economy-v2/quickstart.md | 4 +- .../craftingGame/crafting-game-environment.md | 2 +- .../economy-v2/ugc/index.yml | 2 +- .../economy-monetization/economy/index.yml | 2 +- playfab-docs/economy-monetization/index.yml | 2 +- playfab-docs/get-started/index.yml | 10 +- playfab-docs/get-started/what-is-playfab.md | 12 +- playfab-docs/identity/index.yml | 2 +- .../anonymous-login.md | 38 +++--- .../kongregate-html5.md | 20 +-- .../platform-specific-authentication/toc.yml | 2 +- playfab-docs/index.yml | 8 +- .../gamemanager/reference.md | 72 +++++----- .../live-service-management/index.yml | 2 +- playfab-docs/multiplayer/index.yml | 2 +- .../multiplayer/lobby/create-a-lobby.md | 2 +- playfab-docs/multiplayer/lobby/index.md | 8 +- ...and-matchmaking-real-time-notifications.md | 2 +- .../lobby/lobby-getting-started.md | 2 +- .../lobby-matchmaking-logging.md | 8 +- .../lobby-matchmaking-sdks.md | 8 +- .../multiplayer-unity-sdk-getting-started.md | 4 +- .../multiplayer/lobby/lobby-properties.md | 22 +-- .../functions/pfmultiplayerfindlobbies.md | 2 +- .../pfmatchmaking/pfmatchmaking_members.md | 4 +- .../structs/pfmultiplayerport.md | 4 +- .../structs/pfmultiplayerserverdetails.md | 8 +- .../PlayFab.Multiplayer/MultiplayerPort.md | 4 +- .../MultiplayerPort/MultiplayerPort.md | 2 +- .../MultiplayerServerDetails.md | 8 +- .../MultiplayerServerDetails.md | 6 +- .../PlayFabMultiplayerSDK.md | 4 +- .../unity-multiplayer-api-reference/index.md | 4 +- .../multiplayer/matchmaking/quickstart.md | 14 +- .../networking/concepts-port-usage.md | 12 +- playfab-docs/multiplayer/networking/index.md | 8 +- .../multiplayer/networking/party-features.md | 8 +- .../multiplayer/networking/party-logging.md | 14 +- .../networking/party-playstream-events.md | 2 +- .../multiplayer/networking/party-samples.md | 4 +- .../multiplayer/networking/party-sdks.md | 8 +- .../party-unreal-engine-oss-quickstart.md | 2 +- .../multiplayer/networking/release-notes.md | 121 ++++++++--------- .../networking/unreal-release-notes.md | 4 +- .../servers/deploying-linux-based-builds.md | 2 +- .../directly-debugging-game-servers.md | 2 +- .../multiplayer/servers/os-patch-updates.md | 18 +-- .../servers/server-samples-resources.md | 2 +- .../multiplayer/servers/server-sdks.md | 8 +- .../multiplayer/servers/server-terms.md | 28 ++-- .../multiplayer/servers/vmstartupscript.md | 2 +- playfab-docs/player-progression/index.yml | 2 +- .../player-progression/statistics/index.md | 8 +- playfab-docs/pricing/Meters/meters.md | 4 +- playfab-docs/pricing/Meters/profile-reads.md | 126 +++++++++--------- playfab-docs/pricing/Meters/profile-writes.md | 4 +- playfab-docs/sdks/c-sharp/index.md | 2 +- playfab-docs/sdks/c/index.md | 4 +- playfab-docs/sdks/playfab-sdk-intro.md | 6 +- 74 files changed, 440 insertions(+), 443 deletions(-) diff --git a/playfab-docs/breadcrumb/toc.yml b/playfab-docs/breadcrumb/toc.yml index 0b4ca3ed8..309e333fb 100644 --- a/playfab-docs/breadcrumb/toc.yml +++ b/playfab-docs/breadcrumb/toc.yml @@ -1,37 +1,33 @@ items: -- name: Azure +- name: PlayFab tocHref: /gaming/playfab/ - topicHref: /azure/ + topicHref: /gaming/playfab/ items: - - name: PlayFab - tocHref: /gaming/playfab/ - topicHref: /gaming/playfab/ - items: - - name: Fundamentals - topicHref: /gaming/playfab/get-started/ - - name: Fundamentals - topicHref: /gaming/playfab/whats-new/ - - name: Fundamentals - topicHref: /gaming/playfab/demo-game/ - - name: Fundamentals - topicHref: /gaming/playfab/resources/ - - name: Fundamentals - topicHref: /gaming/playfab/pricing/ - - name: Fundamentals - topicHref: /gaming/playfab/sdks/ - - name: Live service management - topicHref: /gaming/playfab/live-service-management/ - - name: Fundamentals - topicHref: /gaming/playfab/api-references/ - - name: Identity - topicHref: /gaming/playfab/identity/ - - name: Economy, Monetization, & UGC. - topicHref: /gaming/playfab/economy-monetization/ - - name: Multiplayer - topicHref: /gaming/playfab/multiplayer/ - - name: Community - topicHref: /gaming/playfab/community/ - - name: Player progression - topicHref: /gaming/playfab/player-progression/ - - name: Game Data - topicHref: /gaming/playfab/data-analytics/ + - name: Fundamentals + topicHref: /gaming/playfab/get-started/ + - name: Fundamentals + topicHref: /gaming/playfab/whats-new/ + - name: Fundamentals + topicHref: /gaming/playfab/demo-game/ + - name: Fundamentals + topicHref: /gaming/playfab/resources/ + - name: Fundamentals + topicHref: /gaming/playfab/pricing/ + - name: Fundamentals + topicHref: /gaming/playfab/sdks/ + - name: Live service management + topicHref: /gaming/playfab/live-service-management/ + - name: Fundamentals + topicHref: /gaming/playfab/api-references/ + - name: Identity + topicHref: /gaming/playfab/identity/ + - name: Economy, Monetization, & UGC. + topicHref: /gaming/playfab/economy-monetization/ + - name: Multiplayer + topicHref: /gaming/playfab/multiplayer/ + - name: Community + topicHref: /gaming/playfab/community/ + - name: Player progression + topicHref: /gaming/playfab/player-progression/ + - name: Game Data + topicHref: /gaming/playfab/data-analytics/ diff --git a/playfab-docs/community/index.yml b/playfab-docs/community/index.yml index e0875faf9..540538db9 100644 --- a/playfab-docs/community/index.yml +++ b/playfab-docs/community/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Community documentation +title: PlayFab Community documentation summary: PlayFab Community is a set of cross-platform tools and services that enable game creators to build engaging social experiences and foster long term player connections and communities. metadata: diff --git a/playfab-docs/community/leaderboards/index.md b/playfab-docs/community/leaderboards/index.md index 684107747..9f5f74232 100644 --- a/playfab-docs/community/leaderboards/index.md +++ b/playfab-docs/community/leaderboards/index.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Leaderboards overview +title: PlayFab Leaderboards overview author: braulioal -description: Learn about Azure PlayFab Leaderboard. +description: Learn about PlayFab Leaderboard. ms.author: braulioal ms.date: 09/01/2024 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, leaderboard, stats ms.localizationpriority: medium --- -# Azure PlayFab Leaderboards overview +# PlayFab Leaderboards overview -Azure Playfab Leaderboards is a cross-platform service that creates a sorted list of players with the purpose +PlayFab Leaderboards is a cross-platform service that creates a sorted list of players with the purpose of ranking them by scores. Leaderboards can be used as a standalone service or be linked with Statistics (so that updates to statistics feed into the entries on the leaderboard). ![PlayFab Leaderboards Architecture](media/leaderboards-relationship.png) diff --git a/playfab-docs/community/leaderboards/leaderboards-cloudscript.md b/playfab-docs/community/leaderboards/leaderboards-cloudscript.md index ed552009a..8021d97c3 100644 --- a/playfab-docs/community/leaderboards/leaderboards-cloudscript.md +++ b/playfab-docs/community/leaderboards/leaderboards-cloudscript.md @@ -13,20 +13,20 @@ ms.localizationpriority: medium # Leaderboards using Azure Functions In this tutorial, you'll learn how to implement leaderboards using Cloudscript, specifically through [Azure Functions](../../live-service-management/service-gateway/automation/cloudscript-af/index.md). -This approach is particularly powerful because it enables you to create custom server-side logic without requiring client updates. +This approach is powerful because it enables you to create custom server-side logic without requiring client updates. By defining leaderboard-related logic within an Azure Function, your client can invoke that function to execute the code. If changes are needed later, you can update the Azure Function independently—often without modifying the client—depending on the complexity of the update. ## Prerequisites -To follow this tutorial you need to have: -- A PlayFab account, if you don't have one you can create it [here](https://developer.playfab.com/). -- An Azure subscription, if you don't have one you can create it [here](https://azure.microsoft.com/free/). +To follow this tutorial, you need: +- A PlayFab account. If you don't have one, you can create it [here](https://playfab.com/). +- An Azure subscription. If you don't have one, you can create it [here](https://azure.microsoft.com/free/). For more details on how to create an Azure Function check this guide. [Create your first function in Azure using Visual Studio](https://learn.microsoft.com/azure/azure-functions/functions-create-your-first-function-visual-studio) -## Create a Leaderboard using Azure Functions +## Create a leaderboard using Azure Functions -In this section we're going to create a simple leaderboard that will allow us to submit scores and retrieve the top scores. +In this section, we're going to create a leaderboard that allows you to submit scores and retrieve the top scores. ``` C# [Function("LeaderboardExample")] @@ -82,12 +82,12 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano } ``` -- This function attribute ```[Function("LeaderboardExample")]``` defines the name of the function, in this case "LeaderboardExample". +- This function attribute ```[Function("LeaderboardExample")]``` defines the name of the function, in this case `LeaderboardExample`. - The function is triggered by an HTTP request, as indicated by the ```[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")]``` attribute. This means that the function can be accessed via HTTP GET and POST methods without any authentication. -- Within the function, we set the PlayFab Title ID and Developer Secret Key to authenticate our requests to PlayFab services. You can change the way you want to access this values based on what fits best for your particular case and security requirements. +- Within the function, we set the PlayFab Title ID and Developer Secret Key to authenticate our requests to PlayFab services. You can change the way you want to access these values based on what fits best for your particular case and security requirements. - The function checks if the query parameter "leaderboardName" is provided in the request. - Then we call the method ```LoginAsTitleEntity``` to authenticate as a title entity, which is necessary to create leaderboard definitions. -- Finally, we call the method ```CreateLeaderboardDefinitionAsync``` to create a leaderboard definition with the provided name. To find more about creation of leaderboard you can check [Create basic leaderboard](create-basic-leaderboard.md) and [Doing more with leaderboards](doing-more-with-leaderboards.md). +- Finally, we call the method ```CreateLeaderboardDefinitionAsync``` to create a leaderboard definition with the provided name. To find more about creation of leaderboard, you can check [Create basic leaderboard](create-basic-leaderboard.md) and [Doing more with leaderboards](doing-more-with-leaderboards.md). The RunAsync method serves as the entry point for your Azure Function. From there, you can define and call additional methods to build out your custom game logic. How you handle errors or interact with multiple PlayFab services is entirely up to you, giving you full flexibility in your implementation. @@ -97,8 +97,8 @@ Additionally, you can configure automation rules to trigger this Azure Function - [Doing more with leaderboards](doing-more-with-leaderboards.md). - [Create basic leaderboard](create-basic-leaderboard.md). - [Manual tiers](manual-tiers.md). -- [Limits ](limits-leaderboards.md). -- [Quota ](quota-leaderboards.md). +- [Limits](limits-leaderboards.md). +- [Quota](quota-leaderboards.md). - [Seasonal leaderboards](seasonal-leaderboards.md). - [Ranking players by statistics](leaderboards-linked-to-stats.md). - [Add contextual data to leaderboards](metadata-leaderboards.md). diff --git a/playfab-docs/community/leaderboards/leaderboards-linked-to-stats.md b/playfab-docs/community/leaderboards/leaderboards-linked-to-stats.md index bf584b8ec..a61550237 100644 --- a/playfab-docs/community/leaderboards/leaderboards-linked-to-stats.md +++ b/playfab-docs/community/leaderboards/leaderboards-linked-to-stats.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Ranking players by statistics In this tutorial, we're going to learn how to use both Leaderboards and Statistics services together. The end result is that, when a statistic is updated on an entity, is automatically reflected on the corresponding leaderboard. -For more information about Azure PlayFab Statistics, see [Statistics Overview]([Azure PlayFab Statistics overview](../../player-progression/statistics/index.md)). +For more information about PlayFab Statistics, see [Statistics Overview]([PlayFab Statistics overview](../../player-progression/statistics/index.md)). Let's start with an example of a shooter game that uses both services. Here we're going to take advantage of the diff --git a/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md b/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md index e50aff8f9..4eea129ea 100644 --- a/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md +++ b/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md @@ -13,19 +13,19 @@ ms.localizationpriority: medium First, you need an Azure subscription and a storage account. -For existing PlayFab and Azure customers, you can create a storage container on the [Azure portal](https://ms.portal.azure.com/#allservices) and get started with Data Connections on [Azure PlayFab](https://developer.playfab.com). +For existing PlayFab and Azure customers, you can create a storage container on the [Azure portal](https://ms.portal.azure.com/#allservices) and get started with Data Connections on [PlayFab](https://developer.playfab.com/en-US/sign-up). For existing PlayFab who are new to Azure, you can sign up for an [Azure subscription](https://ms.portal.azure.com/). -> [!Note] +> [!NOTE] > Make sure to create your Storage Account in the West US 2, otherwise, egress cost will be applied to your storage account. You can configure up to three Azure Blob Storage accounts in the WestUS2 region. ## Setting up your Storage in Azure -For PlayFab to ingest data in your storage account, container details along with authorization using a SAS token are required. To create a SAS token using the Microsoft Azure portal, follow the steps below. +For PlayFab to ingest data in your storage account, container details along with authorization using a SAS token are required. To create a SAS token using the Microsoft Azure portal, use the following steps. -> [!Note] -> A Storage Account with a restricted network is not supported. All networks must be allowed in the firewall. +> [!NOTE] +> A storage account with a restricted network isn't supported. You must allow all networks in the firewall. ### Option 1: Create the SAS token on the container level. > [!Important] @@ -45,48 +45,48 @@ For PlayFab to ingest data in your storage account, container details along with - Specify the signed key **Start** and **Expiry** times. - Select **Generate SAS token and URL**. - The **Blob SAS token** query string appears in the lower area of the window. -- Copy and paste the **Blob SAS token** values into a **secure location for use in the Azure PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. +- Copy and paste the **Blob SAS token** values into a **secure location for use in the PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. -### Option 2: Create the SAS token on the account level. +### Option 2: Create the SAS token at the account level > [!Important] -> Generate and retrieve the shared access signature for your storage account itself. +> Generate and retrieve the shared access signature for your storage account. - In the [Azure portal](https://ms.portal.azure.com/#allservices), select **Your storage account** -- Select a **Shared access signature** from the list under **Security + Networking**. +- Select **Shared access signature** from the list under **Security + Networking**. - Define **Services** by selecting **blob** and clearing other checkboxes. - Define **Resource Type** by selecting **Container** and **Object** (clear other checkboxes). -- Make sure the **Create**, **Write**, and **List** are selected. +- Make sure the **Create**, **Write**, and **List** permissions are selected. - Specify the signed key **Start** and **Expiry** times. - Select **Generate SAS token and URL**. - The Blob SAS token query string appears in the lower area of the window. -- Copy and paste the **Blob SAS token** values into a **secure location for use in the Azure PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. +- Copy and paste the **Blob SAS token** values into a **secure location for use in the PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. ![Screenshot of SAS token on the account level - Option 2](media/SAS-token-on-the-account-level.png "SAS token on the account level - Option 2") ## Create an Azure Blob Data Connection in PlayFab -### Step 1: Navigate to the data connections tab +### Step 1: Navigate to the Data Connections tab ![Screenshot of PlayFab data connections tab](media/navigate-to-data-connections-tab.png "PlayFab data connections tab") - Login to PlayFab and navigate to your title. -- Click on the “Data” section in the left-hand menu -- Click on the “Data Connections” tab +- Select the **Data** section in the left-hand menu. +- Select the **Data Connections** tab. ### Step 2: Configure a new Data Connection -- Click “New Connection” button. -- Choose the “Destination Type” to be “Azure Blob Storage” -- Populate the fields using the following values +- Select **New Connection**. +- Choose **Azure Blob Storage** as the **Destination Type**. +- Enter the following values for each field: | Value | Details | |:-----------|:-----------| -|Name | The friendly name of your data connection. This name will allow you to find the data connection later to edit it. Put a descriptive name here. +|Name | The friendly name of your data connection. This name allows you to find the data connection later to edit it. Put a descriptive name here. | Account name | The Azure Storage Account. | | Container name | The Azure Storage Account Container. | | Sas token | Either the SAS token generated by the container, or the Blob SAS token query string. | ![Screenshot of configuring and ADX data connection](media/configure-new-data-connection-blob.PNG "ADX data connection configuration") -> [!Note] -> We recommend using a table name that does not exist. If you use an existing table and the schema is not what PlayFab is expecting, then the schema will be modified. +> [!NOTE] +> We recommend using a table name that doesn't exist. If you use an existing table and the schema isn't what PlayFab is expecting, then the schema will be modified. diff --git a/playfab-docs/data-analytics/index.yml b/playfab-docs/data-analytics/index.yml index cd03df823..5bce4b403 100644 --- a/playfab-docs/data-analytics/index.yml +++ b/playfab-docs/data-analytics/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab data and analytics documentation +title: PlayFab data and analytics documentation summary: PlayFab data and analytics helps you manage game data. It provides reporting functions for generating weekly reports and trends, tools for segmenting data and running experiments, and data management tools for ingesting, exporting, and managing data. # < 160 chars metadata: diff --git a/playfab-docs/data-analytics/learn-data/data-explorer/getting-started-with-data-explorer-basic.md b/playfab-docs/data-analytics/learn-data/data-explorer/getting-started-with-data-explorer-basic.md index 24f5dde9e..d42f33acc 100644 --- a/playfab-docs/data-analytics/learn-data/data-explorer/getting-started-with-data-explorer-basic.md +++ b/playfab-docs/data-analytics/learn-data/data-explorer/getting-started-with-data-explorer-basic.md @@ -58,7 +58,7 @@ The table shows the Event Name, Timestamp (UTC), Player ID, and Event Data (via #### What's the sum of order totals this week? ![Order totals sum this week](media/ExplorerBasic_Query_3.png) -#### Are Playfab limits being exceeded? +#### Are PlayFab limits being exceeded? ![Title limits exceeded this week](media/ExplorerBasic_Query_4.png) ### Multi Condition Queries diff --git a/playfab-docs/data-analytics/legacy/insights/best-practices.md b/playfab-docs/data-analytics/legacy/insights/best-practices.md index d474eae28..4996f3eaf 100644 --- a/playfab-docs/data-analytics/legacy/insights/best-practices.md +++ b/playfab-docs/data-analytics/legacy/insights/best-practices.md @@ -103,7 +103,7 @@ Here we examine some best practices for using PlayFab Insights and address the m | Events per entity | 8,000 per second | Exceeding this limit results in a `PerEntityEventRateLimitExceeded` error. An entity most often represents an individual player, but can also be a player group or title. | | Max payload size | 10,240 bytes (10 KB) | | - If you run into any of these limits, contact the Playfab Support team for assistance. In the upper right-hand corner of Game Manager select the question mark icon, then select **Contact Us**. + If you run into any of these limits, contact the PlayFab Support team for assistance. In the upper right-hand corner of Game Manager select the question mark icon, then select **Contact Us**. ### I get an error "Query execution has exceeded the allowed limits" when I try to run a query diff --git a/playfab-docs/data-analytics/legacy/insights/overview.md b/playfab-docs/data-analytics/legacy/insights/overview.md index 22fe2f46f..ee2f34065 100644 --- a/playfab-docs/data-analytics/legacy/insights/overview.md +++ b/playfab-docs/data-analytics/legacy/insights/overview.md @@ -12,48 +12,48 @@ ms.localizationpriority: medium # What is PlayFab Insights? > [!NOTE] -> PlayFab Insights Management was deprecated on December 11th, 2023. We recommend using [Azure Data Explorer (ADX) Connections](../../export-data/data-connection-adx.md) to manage your performance and cost going forward. If your title is still using **Insights**, continue to see this article for feature details. For more information, see [Insights Deprecation Blog](https://developer.microsoft.com/en-us/games/articles/2023/09/playfab-insights-management-to-be-deprecated-starting-december-11/). +> PlayFab Insights Management was deprecated on December 11, 2023. We recommend using [Azure Data Explorer (ADX) Connections](../../export-data/data-connection-adx.md) to manage your performance and cost going forward. If your title is still using **Insights**, continue to see this article for feature details. For more information, see [Insights Deprecation Blog](https://developer.microsoft.com/en-us/games/articles/2023/09/playfab-insights-management-to-be-deprecated-starting-december-11/). -PlayFab Insights is a managed data environment, giving you instant access to your games data without the need for additional engineering. Unlike other hosted data solutions Insights requires no setup, no GDPR work, and no extra engineering. Simply use PlayFab services and your data is available. Automatically ingest and scale, connect external visualization tools, and query freely. +PlayFab Insights is a managed data environment, giving you instant access to your games data without the need for additional engineering. Unlike other hosted data solutions Insights requires no setup, no GDPR work, and no extra engineering. Use PlayFab services and your data is available. Automatically ingest and scale, connect external visualization tools, and query freely. -## Key Features +## Key features Insights key features revolve around data cluster management, data retention, ingestion options, and connectivity to outside tools. -### Automatic Ingestion +### Automatic ingestion PlayFab services automatically fire Playstream events. Any events fired by PlayFab services or created through our SDK are automatically routed to your Insights cluster. There's no need to worry about defining schema or DDL from automatic events. However, the option for sending your own custom events is available. For more information about sending custom events, see the [Custom event overview](../../ingest-data/playstream-overview.md) of Generating PlayStream events. -### Change Your Performance Level To Meet Your Needs +### Change your performance level to meet your needs ![Insights Slider](media/insights-slider.png) Match your cluster performance to your needs minute by minute. Slide your performance level up or down or alternatively schedule your cluster to have different performance levels automatically using scheduled tasks. See [Performance Level & Retention](performance-retention.md) for details. -### Schedule Your Performance Level +### Schedule your performance level ![Scheduled Scaling](media/insights-schedule.png) Use standard cron expressions to automatically scale your cluster up and down during known times. See [Scheduled Scaling](scheduled-scaling.md) for details. -### Keep Your Data as Long as You Need +### Keep your data as long as you need ![Storage and Retention](media/insights-retention.png) Never delete your data or clear your data out every 30 days, whatever is needed for your studio. See [Performance Level & Retention](performance-retention.md) for details. -### Connect Outside Tools +### Connect outside tools Connect Power BI or Grafana for visualization, automate data jobs with Python or Azure Data Factory, explore your data with Azure Data Explorer. See [Connectivity](../connectivity/index.md) for details. -### Export Original or Cleaned Data +### Export original or cleaned data Use the automated export service to export all your data to Azure Blob or AWS S3. See [Exporting Data](export.md) for details. -### Bring Your Own Datasets +### Bring your own datasets Ingest your own custom datasets with [Management Commands](management-commands.md). Merge your custom Playstream events, standard Playstream events, and custom uploaded data to create more robust datasets. -### GDPR Compliant -Standard reporting is tracked and GDPR compliant. Call the playfab GDPR delete request and we'll do the rest. Have custom data you need to delete? No problem, use the [Management Commands](management-commands.md) to maintain your custom data. +### GDPR compliant +Standard reporting is tracked and GDPR compliant. Call the PlayFab GDPR delete request and we'll do the rest. Have custom data you need to delete? No problem, use the [Management Commands](management-commands.md) to maintain your custom data. -## Getting Started with PlayFab Insights -PlayFab Insights is available to all studios right out of the box. The only thing needed to get started is some data. Implement any PlayFab service and you get playstream events automatically sent to your *Insights* or you [can send telemetry directly using PlayFab API calls](xref:titleid.playfabapi.com.events.playstreamevents). Once you have some data check out [Data Explorer](../../export-data/data-connection-quickstart.md). +## Getting started with PlayFab Insights +PlayFab Insights is available to all studios right out of the box. The only thing needed to get started is some data. Implement any PlayFab service and you get playstream events automatically sent to your *Insights* or you [can send telemetry directly using PlayFab API calls](xref:titleid.playfabapi.com.events.playstreamevents). After you have some data, check out [Data Explorer](../../export-data/data-connection-quickstart.md). ## What services are powered by Insights? -PlayFab Insights powers various features and functionality across Game Manager. Adjusting the performance level affects the following across your title: +PlayFab Insights powers various features and functionality across Game Manager. Adjusting the performance level affects the following areas across your title: * Data * Data Explorer (Preview) * Event Export diff --git a/playfab-docs/data-analytics/legacy/insights/performance-retention.md b/playfab-docs/data-analytics/legacy/insights/performance-retention.md index d932d2626..4804cff0c 100644 --- a/playfab-docs/data-analytics/legacy/insights/performance-retention.md +++ b/playfab-docs/data-analytics/legacy/insights/performance-retention.md @@ -1,7 +1,7 @@ --- title: Performance and retention author: joannaleecy -description: Performance and retention for playfab insights +description: Performance and retention for PlayFab insights ms.author: jenelleb ms.date: 02/28/2020 ms.topic: article diff --git a/playfab-docs/data-analytics/legacy/insights/scheduled-scaling.md b/playfab-docs/data-analytics/legacy/insights/scheduled-scaling.md index 6fb59b57c..688eae4ab 100644 --- a/playfab-docs/data-analytics/legacy/insights/scheduled-scaling.md +++ b/playfab-docs/data-analytics/legacy/insights/scheduled-scaling.md @@ -1,7 +1,7 @@ --- title: Scheduled Scaling author: joannaleecy -description: Scheduled Scaling for playfab insights +description: Scheduled Scaling for PlayFab insights ms.author: jenelleb ms.date: 02/28/2020 ms.topic: article diff --git a/playfab-docs/economy-monetization/economy-v2/faq.md b/playfab-docs/economy-monetization/economy-v2/faq.md index 1dfc1985b..b8e46a159 100644 --- a/playfab-docs/economy-monetization/economy-v2/faq.md +++ b/playfab-docs/economy-monetization/economy-v2/faq.md @@ -54,7 +54,7 @@ If your title isn’t live yet, the process is easier but there are differences **Q: Does Economy V2 support all of the features from Economy V1 (Legacy)?** -**A:** No, Economy V2 doesn’t have full parity with all of the features PlayFab supports in V1 (Legacy). Some of these features never received the adoption we hoped for in Playfab. Others were lacking the depth and surface area needed to really help developers implement them in their games. Some we plan to deliver in future updates. Specifically today Economy V2 doesn't support PlayFab style Coupons, Limited Items, Recharge Item Rates, Drop Tables, or Store Support with Segments. +**A:** No, Economy V2 doesn’t have full parity with all of the features PlayFab supports in V1 (Legacy). Some of these features never received the adoption we hoped for in PlayFab. Others were lacking the depth and surface area needed to really help developers implement them in their games. Some we plan to deliver in future updates. Specifically today Economy V2 doesn't support PlayFab style Coupons, Limited Items, Recharge Item Rates, Drop Tables, or Store Support with Segments. ## Marketplace and platform integrations diff --git a/playfab-docs/economy-monetization/economy-v2/fraud-prevention/quickstart.md b/playfab-docs/economy-monetization/economy-v2/fraud-prevention/quickstart.md index dab61b133..c2d35cd43 100644 --- a/playfab-docs/economy-monetization/economy-v2/fraud-prevention/quickstart.md +++ b/playfab-docs/economy-monetization/economy-v2/fraud-prevention/quickstart.md @@ -32,11 +32,11 @@ To give those entries meaning, we need to mirror them in the PlayFab Catalog. Mi Each Bundle can be linked to one or more Partner Marketplace Products by adding an AlternateId to it. The AlternateId is the link between PlayFab and any external IAP Market. When your title calls Redeem for a given player entity, we pass this ID up to the IAP Market to check. The general flow is: 1. Create 1 (or more) real world offers in the Microsoft Store -1. Populate the Add-ons in PlayFab with IAP Market calling permissions and create corresponding Bundles in Playfab that link to the offers you created +1. Populate the Add-ons in PlayFab with IAP Market calling permissions and create corresponding Bundles in PlayFab that link to the offers you created 1. Call `RedeemMicrosoftStoreInventoryItems` > [!NOTE] -> Unlike previous incarnations of Playfab, in the new system you just create one bundle offer, and then you add each market SKU that needs to reference into the AlternateId list. You don’t need to create a new Item for each IAP market. +> Unlike previous incarnations of PlayFab, in the new system you just create one bundle offer, and then you add each market SKU that needs to reference into the AlternateId list. You don’t need to create a new Item for each IAP market. ### Step 1 - Setting up your marketplace integration diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/google.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/google.md index 53e3012d6..1c9f2bc4e 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/google.md +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/google.md @@ -108,7 +108,7 @@ It's time to move on to the [Google Play Console](https://play.google.com/consol ![Add app permissions](../../media/marketplace-integrations/google/add-app-permissions.png) -6. From the list of apps, choose the one you want your account to be linked to. In this case, it's **Economy V2 Playfab Test App**. Once selected, press **Apply**. +6. From the list of apps, choose the one you want your account to be linked to. In this case, it's **Economy V2 PlayFab Test App**. Once selected, press **Apply**. ![App selection](../../media/marketplace-integrations/google/app-selection.png) diff --git a/playfab-docs/economy-monetization/economy-v2/quickstart.md b/playfab-docs/economy-monetization/economy-v2/quickstart.md index 6750d7489..17e9a3c0a 100644 --- a/playfab-docs/economy-monetization/economy-v2/quickstart.md +++ b/playfab-docs/economy-monetization/economy-v2/quickstart.md @@ -197,7 +197,7 @@ Fill in the required metadata – there are only four required properties (_Crea Create a "Draft" Catalog Item by calling the [CreateDraftItem](/rest/api/playfab/economy/catalog/create-draft-item) endpoint: * The EntityToken (from GetEntityToken or other PlayFab `login` call) in the X-EntityToken header -* The Playfab Title ID in the item's CreatorEntity.Id +* The PlayFab Title ID in the item's CreatorEntity.Id ```bash curl \ @@ -355,7 +355,7 @@ Create a Draft Currency Catalog Item by calling the [CreateDraftItem](/rest/api/ * An EntityToken with Catalog Permissions * The Entity.Id as the item 'Creator' -* The Playfab Title ID +* The PlayFab Title ID * The Item should be a Bundle of type 'Currency' and contain a Title and Description Call PublishItem with the ItemId returned from the CreateDraftItem. diff --git a/playfab-docs/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment.md b/playfab-docs/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment.md index 91dde9d3c..f9a4fc398 100644 --- a/playfab-docs/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment.md +++ b/playfab-docs/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment.md @@ -51,6 +51,6 @@ If you followed the steps so far, the package manager should now be open in VS. Once you have the appropriate source added to the package manager, you should now be able to search for the PlayFab SDK, called **PlayFabAllSDK**. This search should return some available packages, the one you're looking for shares the exact name mentioned previously, and looks like this: -![Playfab SDK](../../media/crafting-game-images/pf-sdk.png) +![PlayFab SDK](../../media/crafting-game-images/pf-sdk.png) Once installed you can start using all of the PlayFab API functions! We can now move on to the next step. diff --git a/playfab-docs/economy-monetization/economy-v2/ugc/index.yml b/playfab-docs/economy-monetization/economy-v2/ugc/index.yml index 830c6b87c..531c154c2 100644 --- a/playfab-docs/economy-monetization/economy-v2/ugc/index.yml +++ b/playfab-docs/economy-monetization/economy-v2/ugc/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab UGC documentation # < 60 chars +title: PlayFab UGC documentation # < 60 chars summary: summary # < 160 chars metadata: diff --git a/playfab-docs/economy-monetization/economy/index.yml b/playfab-docs/economy-monetization/economy/index.yml index 89816056c..4b697db84 100644 --- a/playfab-docs/economy-monetization/economy/index.yml +++ b/playfab-docs/economy-monetization/economy/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Economy documentation # < 60 chars +title: PlayFab Economy documentation # < 60 chars summary: PlayFab Economy provides you with the necessary features to more deeply engage with your community and monetize your game. # < 160 chars metadata: diff --git a/playfab-docs/economy-monetization/index.yml b/playfab-docs/economy-monetization/index.yml index 04d08668e..81d801050 100644 --- a/playfab-docs/economy-monetization/index.yml +++ b/playfab-docs/economy-monetization/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Economy v2 documentation # < 60 chars +title: PlayFab Economy v2 documentation # < 60 chars summary: PlayFab Economy v2 provides a platform to build and grow marketplaces, progression, and engagement that scale with your players. # < 160 chars metadata: diff --git a/playfab-docs/get-started/index.yml b/playfab-docs/get-started/index.yml index f4bd6f9f4..4315f0c7b 100644 --- a/playfab-docs/get-started/index.yml +++ b/playfab-docs/get-started/index.yml @@ -1,11 +1,11 @@ ### YamlMime:Landing -title: Azure PlayFab fundamentals -summary: From pre-production to post-launch, learn how PlayFab can help you build and operate your game. # < 160 chars +title: PlayFab fundamentals +summary: From preproduction to post-launch, learn how PlayFab can help you build and operate your game. # < 160 chars metadata: - title: Azure PlayFab fundamentals and getting started documentation - description: From pre-production to post-launch, learn how PlayFab can help you build and operate your game. # Required; article description that is displayed in search results. < 160 chars. + title: PlayFab fundamentals and getting started documentation + description: From preproduction to post-launch, learn how PlayFab can help you build and operate your game. # Required; article description that is displayed in search results. < 160 chars. ms.service: azure-playfab #Required; service per approved list. service slug assigned to your service by ACOM. ms.topic: landing-page author: m-kdearnley @@ -22,7 +22,7 @@ landingContent: linkLists: - linkListType: overview links: - - text: What is Playfab? + - text: What is PlayFab? url: what-is-playfab.md - linkListType: concept links: diff --git a/playfab-docs/get-started/what-is-playfab.md b/playfab-docs/get-started/what-is-playfab.md index 8ee3193d7..8ec6b1d4e 100644 --- a/playfab-docs/get-started/what-is-playfab.md +++ b/playfab-docs/get-started/what-is-playfab.md @@ -10,11 +10,11 @@ keywords: playfab, analytics, multiplayer, authentication, leaderboards, liveops ms.localizationpriority: medium --- -# What is Azure PlayFab? +# What is PlayFab? -Azure PlayFab is a complete backend platform for games, featuring managed game services, real-time analytics, and live operations management capabilities. These features help you engage and retain players, monetize your experiences, collect and analyze game data, and build player experiences across gaming platforms and devices. +PlayFab is a complete backend platform for games, featuring managed game services, real-time analytics, and live operations management capabilities. These features help you engage and retain players, monetize your experiences, collect and analyze game data, and build player experiences across gaming platforms and devices. -PlayFab's cost-effective and highly-scalable solutions are backed by the world-class infrastructure and a global reach of Azure, allowing all game creators to build and launch their games with confidence. Whether you are a team of one or one thousand, PlayFab has solutions that scale for all sizes of game. PlayFab is the perfect complement to your game: choose which PlayFab features you want to use, extend PlayFab capabilities with cloud-based logic, or connect PlayFab with your own bespoke game services. +PlayFab's cost-effective and highly-scalable solutions are backed by the world-class infrastructure and a global reach of Azure, allowing all game creators to build and launch their games with confidence. Whether you're a team of one or one thousand, PlayFab has solutions that scale for all sizes of game. PlayFab is the perfect complement to your game: choose which PlayFab features you want to use, extend PlayFab capabilities with cloud-based logic, or connect PlayFab with your own bespoke game services. By managing the essential backend components, PlayFab can help you and your team devote more time to innovating and perfecting the elements of your game that matter most. @@ -38,11 +38,11 @@ PlayFab provides the following services: ## Cross-network identity -**Player authentication**: Start with frictionless authentication and let players link accounts to roam across Windows, Xbox, Steam, PlayStation™Network, Nintendo, Facebook, iOS, Android, and more. +**Player authentication**: Start with frictionless authentication and let players link accounts to roam across Windows, Xbox, Steam, PlayStation™ Network, Nintendo, Facebook, iOS, Android, and more. ## Live service management -**Game Manager web portal**: A shared space (with roles and access permissions) where studio members can build, configure and operate your game. +**Game Manager web portal**: A shared space (with roles and access permissions) where studio members can build, configure, and operate your game. **Title data**: Manage your game configuration remotely. @@ -90,7 +90,7 @@ PlayFab provides the following services: ## Community -**Leaderboards**: Facilitate permanent or time-limited competitions amongst friends or strangers. +**Leaderboards**: Facilitate permanent or time-limited competitions among friends or strangers. ### Chat diff --git a/playfab-docs/identity/index.yml b/playfab-docs/identity/index.yml index 9f390886d..91de3995f 100644 --- a/playfab-docs/identity/index.yml +++ b/playfab-docs/identity/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Identity documentation +title: PlayFab Identity documentation summary: Overviews, quickstarts, and tutorials that provide guidance on player login and GameManager authentication. # < 160 chars metadata: diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md b/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md index 7d5b168c7..00c164c80 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md @@ -10,7 +10,7 @@ keywords: playfab, authentication, server, anonymous login, customid ms.localizationpriority: medium --- -# Setting up Playfab Authentication using Anonymous Login +# Setting up PlayFab Authentication using Anonymous Login This guide shows you how to implement PlayFab authentication using anonymous login APIs with server-side protection, focusing only on CustomID authentication using HTML5/JavaScript. @@ -26,7 +26,7 @@ To enhance the security of anonymous login, PlayFab implemented a crucial securi - Disabling client-side player creation prevents unauthorized account creation directly from unauthorized clients. - Only existing players can log in through client-side APIs. -2. **Enabled Server-Side Player Creation**: +1. **Enabled server-side player creation**: - Player account creation is now handled through server-side APIs (`LoginWithCustomID`, `LoginWithAndroidDeviceID`, `LoginWithIOSDeviceID`, `LoginWithNintendoDeviceId`). - This ensures all account creation happens in a secure, controlled environment. @@ -41,9 +41,9 @@ To enhance the security of anonymous login, PlayFab implemented a crucial securi > [!NOTE] > If you need help with setting up a server, see the [Running an HTTP server for testing](running-an-http-server-for-testing.md) tutorial. Throughout this guide, we'll assume your domain is `http://playfab.example`. -## Authentication Flow +## Authentication flow -1. **Server-side Account Creation**: +1. **Server-side account creation**: - Use `Server/LoginWithCustomID` with the server API to create new players - Requires a title secret key - Reference: [Server API - Login With Custom ID](xref:titleid.playfabapi.com.server.authentication.loginwithcustomid) @@ -52,9 +52,9 @@ To enhance the security of anonymous login, PlayFab implemented a crucial securi - Use `Client/LoginWithCustomID` with the client API to log in existing players - Reference: [Client API - Login With Custom ID](xref:titleid.playfabapi.com.client.authentication.loginwithcustomid) -## Implementation Steps +## Implementation steps -### 1. Set Up Your Development Environment +### 1. Set up your development environment 1. Download the JavaScript SDK from the [JavaScript SDK documentation](https://learn.microsoft.com/gaming/playfab/sdks/javascript/) 2. Install the required Node.js packages: @@ -63,7 +63,7 @@ To enhance the security of anonymous login, PlayFab implemented a crucial securi npm install playfab-sdk ``` -### 2. Server-Side Implementation (Node.js) +### 2. Server-side implementation (Node.js) > [!IMPORTANT] > Keep your title secret key secure and never expose it in client-side code. The secret key should only be used in secure server environments. @@ -121,7 +121,7 @@ server.listen(port, () => { }); ``` -### 3. Client-Side Implementation (HTML) +### 3. Client-side implementation (HTML) ```html @@ -160,18 +160,18 @@ server.listen(port, () => { ``` -## Configuring Player Creation Settings +## Configuring player creation settings -### For Existing Titles +### For existing titles 1. Navigate to the PlayFab developer portal and select your title -2. Go to **Settings** -3. Select the **API Features** tab +1. Go to **Settings**. +1. Select the **API Features** tab. 4. Check the box to prevent new player accounts from being created via anonymous login APIs ![Disabling player creation using Client/LoginWithCustomId](media/tutorials/anonymous-html5/existing_title.png) -### For New Titles +### For new titles > [!WARNING] > Enabling automatic player creation for anonymous login APIs can compromise security. Only enable this feature temporarily during development or testing. Always disable it before moving to production. @@ -179,16 +179,16 @@ server.listen(port, () => { New titles have player creation via anonymous APIs disabled by default. To enable for testing, perform the following: 1. Navigate to the PlayFab developer portal and select your title -2. Go to **Settings** -3. Select the **API Features** tab +1. Go to **Settings**. +1. Select the **API Features** tab. 4. Uncheck the box to allow new player accounts from being created via anonymous login APIs ![Enabling player creation using Client/LoginWithCustomId](media/tutorials/anonymous-html5/new_title.png) -## Testing and Response Examples +## Testing and response examples -### Server Response Example +### Server response example When successfully creating a user through the server API, you receive a response similar to: @@ -204,7 +204,7 @@ When successfully creating a user through the server API, you receive a response } ``` -### Client Response Example +### Client response example When attempting to create a new account from the client API (which is now disabled), you receive an error: @@ -229,7 +229,7 @@ When successfully logging in an existing user through the client API: } } ``` -## Further Reading +## Further reading - [PlayFab Authentication Overview](../authentication/index.md) - [Login Basics and Best Practices](../login/login-basics-best-practices.md) diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/kongregate-html5.md b/playfab-docs/identity/player-identity/platform-specific-authentication/kongregate-html5.md index b87e45e9b..6b32dc530 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/kongregate-html5.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/kongregate-html5.md @@ -40,11 +40,11 @@ To do this, we need to prepare an `index.html` file with the following content. Navigate to the [Kongregate website](https://www.kongregate.com/): 1. Select the **Games** tab. -2. Then select the **Upload your game** button. +1. Select the **Upload your game** button. ![Kongregate Games tab](media/tutorials/kongregate-games-tab.png) -A page to set up for a new application will open. +A page to set up for a new application opens. 1. Enter the **Application Name** in the **Title** field. 2. Then enter a **Game Description** in the field provided. @@ -53,9 +53,9 @@ A page to set up for a new application will open. ![Kongregate upload your game](media/tutorials/kongregate-upload-your-game.png) -You will be moved to the **Application Upload** page. +You'll be moved to the **Application Upload** page. -As a *very* important first step, make sure to save the **URL** from your **Web Address Bar**. This will save you a lot of time trying to restore access to the application once you close the page. +As an important first step, make sure to save the **URL** from your **Web Address Bar**. This saves you a lot of time trying to restore access to the application once you close the page. 1. Once this is done, select the prepared **index.html** file as your **Game File**. 2. Then set up the screen size. @@ -78,14 +78,14 @@ As a *very* important first step, make sure to save the **URL** from your **Web In your PlayFab title Game Manager: 1. Navigate to **Add-ons**. -2. Then locate and select **Kongregate**, as shown in the example provided below. +1. Find and select **Kongregate**. ![PlayFab select Kongregate Add-on](media/tutorials/playfab-select-kongregate-add-on.png) -A new page will open, allowing you to set up **Kongregate** integration. +A new page opens, allowing you to set up **Kongregate** integration. 1. Enter the **API Key** you acquired in the previous section. -2. Select the **Install Kongregate** button. +1. Select **Install Kongregate**. ![PlayFab set up Kongregate integration](media/tutorials/playfab-set-up-kongregate-integration.png) @@ -145,7 +145,7 @@ Use the example code shown below to populate the `index.html` for your game. // The function prepares and triggers PlayFab LoginWithKongregate API call function loginInUsingPlayFab() { - // Setting up playfab title ID + // Setting up PlayFab title ID PlayFab.settings.titleId = "159F"; // forming request @@ -184,7 +184,7 @@ Use the example code shown below to populate the `index.html` for your game. ## Testing -Remember that URL we asked you to save in a safe and accessible place a little earlier? Use it now to access your **Application Upload** page. +Remember that URL we asked you to save in a safe and accessible place a little earlier? Use it now to access your **Application Upload** page. 1. Select **index.html** as your **Game File**. 2. Set up the screen size. @@ -197,6 +197,6 @@ Once the preview loads, wait for the Application to obtain the **Kongregate User - When that has happened, select the **PlayFab Login With Kongregate** button. - After a brief pause, you should receive an **Authenticated via PlayFab** message. -- At this point you have successfully logged in using PlayFab and Kongregate! +- At this point, you have successfully logged in using PlayFab and Kongregate! ![Testing PlayFab Login with Kongregate](media/tutorials/kongregate-html5/testing-playfab-login-with-kongregate.png) diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml b/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml index d5c88b4e4..7e3d2e2dd 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml @@ -37,5 +37,5 @@ href: xbox-live-add-on.md - name: Integrating the Universal Windows Platform with PlayFab href: uwp-integration.md - - name: Setting up Playfab Authentication using Anonymous Login + - name: Setting up PlayFab Authentication using Anonymous Login href: anonymous-login.md diff --git a/playfab-docs/index.yml b/playfab-docs/index.yml index ba4411f27..2bd5df06c 100644 --- a/playfab-docs/index.yml +++ b/playfab-docs/index.yml @@ -1,12 +1,12 @@ ### YamlMime:Hub # root section (required) -title: Azure PlayFab documentation -summary: Learn how to build and manage engaging games using Microsoft Azure PlayFab services. -# brand: playfab +title: PlayFab documentation +summary: Learn how to build and manage engaging games using Microsoft PlayFab services. +# brand: PlayFab metadata: - title: Azure PlayFab documentation + title: PlayFab documentation description: PlayFab is a complete backend platform for live games. services: service ms.service: azure-playfab diff --git a/playfab-docs/live-service-management/gamemanager/reference.md b/playfab-docs/live-service-management/gamemanager/reference.md index 60e1ecf70..afe986e05 100644 --- a/playfab-docs/live-service-management/gamemanager/reference.md +++ b/playfab-docs/live-service-management/gamemanager/reference.md @@ -12,9 +12,9 @@ ms.localizationpriority: medium # Game Manager reference -This reference familiarizes you with the high-level aspects of the Game Manager. For more detailed information, you may select your specific topic of interest in the PlayFab documentation that follows. +This reference familiarizes you with the high-level aspects of the Game Manager. For more detailed information, select your specific article of interest in the PlayFab documentation that follows. -To get the most value from this topic, you should have created your PlayFab account, logged in, and viewed the Game Manager for your title, even if it's an empty title for now. +To get the most value from this article, you should create your PlayFab account, logged in, and viewed the Game Manager for your title, even if it's an empty title for now. The sections provided below offer greater insight on each Game Manager area. Each time you perform an API call or task, view the results in the Game Manager in the appropriate area for that task. @@ -29,24 +29,24 @@ Game Manager is split into four major sections: - Engage – Facilitate connections with players. - Analyze – Monitor and act on player behaviors. -## Title Overview +## Title overview An overview of the recent and less-recent performance of your title. -**Overview** - shows your game's basic statistics and what you may have assigned as Key Performance Indicators (KPIs). In the upper-right, you will find time period toggle buttons, and there are also filters for the tables. +**Overview** - shows your game's basic statistics and what you assigned as Key Performance Indicators (KPIs). In the upper-right, you'll find time period toggle buttons. There are also filters for the tables. -- **4h**: This will load data generated within the last 4 hours. -- **24h**: This will load data generated within the last 24 hours. -- **3d**: This will load data generated within the last 3 days. -- **7d**: This will load data generated within the last 7 days. -- **mtd**: This will load data generated within the current month. +- **4h**: This loads data generated within the last 4 hours. +- **24h**: This loads data generated within the last 24 hours. +- **3d**: This loads data generated within the last three days. +- **7d**: This loads data generated within the last seven days. +- **mtd**: This loads data generated within the current month. > [!NOTE] > In Game Manager, all times are displayed in local time. ![Game Manager - Dashboards](media/tutorials/game-manager-dashboard.png) -The tables in the Overview tab allow you to monitor PlayStream events in real time. They include the following: +The tables in the Overview tab allow you to monitor PlayStream events in real time. They include the following metrics: - **Unique Users**: The average number of unique players logging in per day. - **API Calls**: Indicates how many API calls were executed within the given time period. @@ -70,7 +70,7 @@ In this section of the Game Manager, a sorted list is presented, and organized b ![Game Manager - Players Tab](media/tutorials/game-manager-players-tab.png) -**Overview** - this detailed screen provides a wealth of insight into the players' activities. The sub-menu contains many links to other player-centric information, as shown below. +**Overview** - this detailed screen provides a wealth of insight into the players' activities. The submenu contains many links to other player-centric information, as shown below. ![Game Manager - Player - Overview](media/tutorials/game-manager-player-overview.png) @@ -92,9 +92,9 @@ Some specific tools your team can use to remedy defrauded players and identify p Multiplayer allows you to configure server hosting and matchmaking. -**Servers** - Whether you are looking to hosting multi-player matches or just need a secure environment that can reduce many common forms of hacking and abuse, the PlayFab Thunderhead servers work with many architectures and game types. These servers provide an excellent alternative when compared with the overhead of dedicated game servers. +**Servers** - Whether you're looking to hosting multi-player matches or just need a secure environment that can reduce many common forms of hacking and abuse, the PlayFab Thunderhead servers work with many architectures and game types. These servers provide an excellent alternative when compared with the overhead of dedicated game servers. -**Matchmaking** - Set up your matchmaking queues by configuring match sizes, servers and statistics. +**Matchmaking** - Set up your matchmaking queues by configuring match sizes, servers, and statistics. ![Matchmaking](media/tutorials/game-manager-multiplayer-matchmaking.png) @@ -129,7 +129,7 @@ To configure marketplace integrations for your title: Explore the **Add-ons** se ![Game Manager - Add-ons - Partner Add-ons](media/tutorials/game-manager-add-ons-partner-add-ons.png) -Setup instructions for each add-on may vary. Additional billing information may also be required. +Setup instructions for each add-on vary. More billing information might also be required. [Back to About the Game Manager](#about-game-manager) @@ -149,7 +149,7 @@ As an example, the following image shows the primary catalogs for **Unicorn Batt **Items** - An item within the catalog. Items can be of several different types. -**Stores**- A subset of catalog items that can be set to prices that are different than those specified by the catalog. +**Stores**- A subset of catalog items that can be set to prices that are different than prices specified by the catalog. ![Game Manager - Economy - Catalogs - Edit Container](media/tutorials/game-manager-economy-catalogs-edit-container.png) @@ -171,7 +171,7 @@ Additional Information: ### User Generated Content -The User Generated Content tab displays all published content for your title. When enabled, all users can create, discover, and consume content. +The **User Generated Content** (UGC) tab displays all published content for your title. When enabled, all users can create, discover, and consume content. ![UGC Landing Page](media/tutorials/game-manager-ugc.png) @@ -196,15 +196,15 @@ Additional Information: ### Progression -The Progression tab displays all the active stats and leaderboards for your title. [Playfab Statistics](../../player-progression/statistics/index.md) and [PlayFab Leaderboards](../../community/leaderboards/quickstart-leaderboards.md) can be defined and configured here. You can even link a leaderboard to a stat to have one call drive updates for both. +The Progression tab displays all the active stats and leaderboards for your title. [PlayFab Statistics](../../player-progression/statistics/index.md) and [PlayFab Leaderboards](../../community/leaderboards/quickstart-leaderboards.md) can be defined and configured here. You can even link a leaderboard to a stat to have one call drive updates for both. - [Back to About the Game Manager](#about-game-manager) ### Content -The Content section offers tools for engaging with your players. The content can include news, remote configuration, and files. +The Content section offers tools for engaging with your players. The content can include news, remote configuration, and files. -**Title Data** - Here you can configure and store key properties which you can change after your game launches. Title data is accessible from all API sets by all users. Because of this, title data is an ideal place to store your custom title settings. Internal data is hidden from game clients and only available on your game servers. +**Title Data** - Here you can configure and store key properties that you can change after your game launches. Title data is accessible from all API sets by all users. Because of this, title data is an ideal place to store your custom title settings. Internal data is hidden from game clients and only available on your game servers. ### Add or edit title data keys @@ -222,11 +222,11 @@ The Content section offers tools for engaging with your players. The content ca **Title News** - Create title news for your game title. As needed, add additional languages. -**File Management** - Create, organize and upload files for your game client via the Content Delivery Network (CDN). +**File Management** - Create, organize, and upload files for your game client via the Content Delivery Network (CDN). > [!NOTE] > There are varying time delays, depending on the type of file handling that is required. For detailed information, view the online Help for the File Management tab. -**Email Templates** - Create, configure and manage email templates for game clients. +**Email Templates** - Create, configure, and manage email templates for game clients. The following example shows the **Email Templates** tab for *Great Game*. @@ -242,11 +242,11 @@ Analyze allows you to monitor and act on player behaviors. ### Dashboards -Dashboards allow you to see Trends, run Reports and perform Diagnostics. +Dashboards allow you to see Trends, run Reports, and perform Diagnostics. ### Data -In the **Data** area you can do a number of things to track and analyze data from your players' activities. There are a number of graphing and reports capabilities that provide the ability to consolidate and visualize the data. +In the **Data** area, you can do many things to track and analyze data from your players' activities. There are a number of graphing and reports capabilities that provide the ability to consolidate and visualize the data. **Trends** - Configure and view trends for a number of statistics for time periods ranging from 7 days to 26 months. The Trends graph shows classic retention - only new players that have returned - for the chosen time period. The 30-day retention report includes both new and returning players. **Event History** - Search and display a number of different Event History types, depending on the query you create. Use event name, date range, or event values. @@ -254,7 +254,7 @@ In the **Data** area you can do a number of things to track and analyze data fro ![Game Manager - Reports](media/tutorials/game-manager-analytics-reports.png) -For additional or custom reports, please open a feature request in our [community forums](https://community.playfab.com/spaces/24/index.html). +For additional or custom reports, open a feature request in our [community forums](https://community.playfab.com/spaces/24/index.html). **Webhooks** - Webhooks allow you to have some or all of your PlayStream events forwarded to any web URL you want. The event data is sent via POST in the request body as JSON. @@ -281,7 +281,7 @@ On the Audit History page, select any entry in the log to view the complete deta Access the title settings from the Settings menu. -**General** - Provides basic information that you will use to configure your title such as player display names and the default language for your title. +**General** - Provides basic information that you'll use to configure your title such as player display names and the default language for your title. ![Game Manager - Settings - General Tab](media/tutorials/game-manager-settings-general.png) @@ -294,12 +294,12 @@ Choose your preferred options, and select the **Save** button. **Secret Keys** - Allows you to create and manage your PlayFab secret keys, the unique identifier for your game when making Admin and server API calls. > [!IMPORTANT] -> This key should only be shared with trusted members of your development team, since it enables API calls that can affect game data and player accounts. Never share your PlayFab API secret key with anyone; doing so may jeopardize your title's security. +> This key should only be shared with trusted members of your development team, since it enables API calls that can affect game data and player accounts. Never share your PlayFab API secret key with anyone; doing so might jeopardize your title's security. **Email Preferences** - Allows you to configure e-mail settings such as Subscription and Reply-To addresses. **Push Notifications** - Configure notifications to be sent to android or iOS devices. **Limits** - Set limits on certain PlayFab features, economic or otherwise in your game. -**Client Profile Options** - Allows you to configure what a Client can or cannot access and configure on their own for the title. +**Client Profile Options** - Allows you to configure what a Client can or can't access and configure on their own for the title. ## Other basic actions @@ -316,7 +316,7 @@ Choose your preferred options, and select the **Save** button. ### View PlayFab news -New notifications will be indicated in the little bell icon in the upper-right corner of your window. +New notifications are indicated in the little bell icon in the upper-right corner of your window. 1. Select icon to display **News**. 2. View the news from the PlayFab team, ordered by the most recent, first. The news feeds include information on new features, API updates, and service outages. @@ -325,18 +325,18 @@ New notifications will be indicated in the little bell icon in the upper-right c ### Create and edit studios and titles -In this section you learn how to create and manage studios and game titles. +In this section, you learn how to create and manage studios and game titles. **To add a new studio:** -1. Click the PlayFab icon to display the **My Studios** and **Titles** pages. -2. Click **NEW STUDIO** to create a new studio in the dialog that appears. +1. Select the PlayFab icon to display the **My Studios** and **Titles** pages. +2. Select **NEW STUDIO** to create a new studio in the dialog that appears. 3. Enter a **Studio Name** and **Authentication provider**. 4. Save your changes and return to the My Studios and Titles page. **To edit an existing studio:** -1. Select the elipsis drop-down menu to the right side of your **Studio name**, then select **Studio settings**. +1. Select the ellipsis drop-down menu to the right side of your **Studio name**, then select **Studio settings**. ![Game manager - Edit Studio](media/tutorials/game-manager-mystudiosandtitles-settings.png) 2. Make your edits. @@ -345,7 +345,7 @@ In this section you learn how to create and manage studios and game titles. **To add a new title:** 1. Select the drop-down menu to the right side of your Studio's Name, and then select **New title** to display the Create Title page. -2. Enter the details and click the **CREATE TITLE** button. +2. Enter the details and select the **CREATE TITLE** button. ![Game manager - Create a new game](media/tutorials/game-manager-create-title.png) 3. Save your changes and return to the My Studios and Titles page. @@ -360,12 +360,12 @@ In this section you learn how to create and manage studios and game titles. ### About User Accounts -You can create user accounts that are individual or Admin-level accounts. Admin accounts provide access to one or more sections on one or more titles of a given studio, and of course provide full ability to configure studio and title information. +You can create user accounts that are individual or Admin-level accounts. Admin accounts provide access to one or more sections on one or more titles of a given studio, and provide full ability to configure studio and title information. ![Game manager - Studio Users](media/tutorials/game-manager-studio-users.png) 1. Select the drop-down menu to the far right from your Studio name, and then select **Studio users**. 2. Choose **ADD USER** to display the Add New User page. Check the box if you want to make the user an Admin. -3. To remove accounts in the **Users** page, simply select **Remove**. +3. To remove accounts in the **Users** page, select **Remove**. -If you do not already have a PlayFab Admin account, an e-mail will be sent to the address you provided. Upon confirmation, the new account will have access to the Studio and title. +If you don't already have a PlayFab Admin account, an e-mail is sent to the address you provided. Upon confirmation, the new account has access to the Studio and title. diff --git a/playfab-docs/live-service-management/index.yml b/playfab-docs/live-service-management/index.yml index c2ea92f22..02960eef0 100644 --- a/playfab-docs/live-service-management/index.yml +++ b/playfab-docs/live-service-management/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Live service management documentation +title: PlayFab Live service management documentation summary: Manage and optimize your game effectively with game configuration and title data, player segmentation for targeted configuration and AB testing, and title-wide communication tools. # < 160 chars metadata: diff --git a/playfab-docs/multiplayer/index.yml b/playfab-docs/multiplayer/index.yml index b7a6b9826..c423a889c 100644 --- a/playfab-docs/multiplayer/index.yml +++ b/playfab-docs/multiplayer/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Multiplayer documentation +title: PlayFab Multiplayer documentation summary: PlayFab Multiplayer services support real-time multiplayer capabilities for matchmaking, grouping, networking, and server hosting. # < 160 chars metadata: diff --git a/playfab-docs/multiplayer/lobby/create-a-lobby.md b/playfab-docs/multiplayer/lobby/create-a-lobby.md index bb523de61..66c0e8ad2 100644 --- a/playfab-docs/multiplayer/lobby/create-a-lobby.md +++ b/playfab-docs/multiplayer/lobby/create-a-lobby.md @@ -24,7 +24,7 @@ There are several ways a lobby can be created. From a technical perspective, all lobbies are fall into two main categories based on ownership—server-owned and client-owned. To learn more, see [Owner requirements and privileges](owner-requirements-and-privileges.md). -The general usage of PlayFab Lobby is to temporarily hold a group of players together. For commonly used applications of Lobby, see the [Azure PlayFab Lobby overview](index.md). +The general usage of PlayFab Lobby is to temporarily hold a group of players together. For commonly used applications of Lobby, see the [PlayFab Lobby overview](index.md). ### Supported entity types diff --git a/playfab-docs/multiplayer/lobby/index.md b/playfab-docs/multiplayer/lobby/index.md index d7f2cbb4b..5892e9f89 100644 --- a/playfab-docs/multiplayer/lobby/index.md +++ b/playfab-docs/multiplayer/lobby/index.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Lobby overview +title: PlayFab Lobby overview author: joannaleecy -description: Learn about Azure PlayFab Lobby. +description: Learn about PlayFab Lobby. ms.author: jenelleb ms.date: 04/08/2025 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, lobby, matchmaking ms.localizationpriority: medium --- -# Azure PlayFab Lobby overview +# PlayFab Lobby overview -Azure PlayFab Lobby is a service to create a temporary grouping mechanism for players to play games together. It's frequently used together with matchmaking, allowing for pre-formed groups to join the same matchmaking ticket, or allowing matched players to convene and receive further notifications about the group such as join/leave events or server connection details. +PlayFab Lobby is a service to create a temporary grouping mechanism for players to play games together. It's frequently used together with matchmaking, allowing for pre-formed groups to join the same matchmaking ticket, or allowing matched players to convene and receive further notifications about the group such as join/leave events or server connection details. ## Benefits diff --git a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md index 5ed1b9db7..80ffe2473 100644 --- a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md +++ b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md @@ -14,7 +14,7 @@ ms.date: 03/14/2022 The Matchmaking and Lobby features have built in support for real-time notifications. Notifying players of changes to Matchmaking or Lobby has never -been easier, as the work to handle notifications is done for you in the [Azure PlayFab Lobby and Matchmaking SDK](lobby-matchmaking-sdks/lobby-matchmaking-sdks.md). New APIs will +been easier, as the work to handle notifications is done for you in the [PlayFab Lobby and Matchmaking SDK](lobby-matchmaking-sdks/lobby-matchmaking-sdks.md). New APIs will allow connected clients to subscribe for notifications of Lobby and Matchmaking changes. With this addition, you'll no longer need to poll for changes to matches or lobbies. diff --git a/playfab-docs/multiplayer/lobby/lobby-getting-started.md b/playfab-docs/multiplayer/lobby/lobby-getting-started.md index 7a1b739c0..04e3dbfef 100644 --- a/playfab-docs/multiplayer/lobby/lobby-getting-started.md +++ b/playfab-docs/multiplayer/lobby/lobby-getting-started.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Lobby SDK Quickstart -This article describes how to set up the development environment for Azure PlayFab Lobby and create your first lobby using the PlayFab Multiplayer C/C++ SDK. +This article describes how to set up the development environment for PlayFab Lobby and create your first lobby using the PlayFab Multiplayer C/C++ SDK. > [!NOTE] > The PlayFab Multiplayer SDK also provides APIs for PlayFab Matchmaking. diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-logging.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-logging.md index 73b8d1ac2..361af022f 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-logging.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-logging.md @@ -1,7 +1,7 @@ --- -title: Diagnostic tracing/logging in Azure PlayFab Lobby and Matchmaking SDKs +title: Diagnostic tracing/logging in PlayFab Lobby and Matchmaking SDKs author: vicodex -description: Learn about tracing/logging in the SDKs for Azure PlayFab Lobby and Matchmaking. +description: Learn about tracing/logging in the SDKs for PlayFab Lobby and Matchmaking. ms.author: victorku ms.date: 10/26/2022 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, networking, party, sdk, sample ms.localizationpriority: medium --- -# Tracing/logging instructions for Azure Playfab Lobby and Matchmaking SDKs +# Tracing/logging instructions for PlayFab Lobby and Matchmaking SDKs -This topic describes how to capture diagnostic traces generated by the Azure PlayFab Lobby and Matchmaking SDKs. +This topic describes how to capture diagnostic traces generated by the PlayFab Lobby and Matchmaking SDKs. > [!NOTE] > Our SDKs undergo internal testing before every release to ensure the expected level of functionality and normally don't require logging to be enabled by default, particularly in the shipping version of your game. diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md index 6522f75fc..2e2ffc15e 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Lobby and Matchmaking SDKs +title: PlayFab Lobby and Matchmaking SDKs author: PushpadantK -description: Learn about the SDKs for Azure PlayFab Lobby and Matchmaking. +description: Learn about the SDKs for PlayFab Lobby and Matchmaking. ms.author: pkacha ms.date: 11/30/2021 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, matchmaking, lobby, sdk, sample ms.localizationpriority: medium --- -# Azure Playfab Lobby and Matchmaking SDKs +# PlayFab Lobby and Matchmaking SDKs -This article describes all the Azure PlayFab Lobby and Matchmaking SDKs that are currently available. +This article describes all the PlayFab Lobby and Matchmaking SDKs that are currently available. If you don't find what you need, let us know by writing a post on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started.md index fb24b18cd..310576813 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Multiplayer getting started for Unity +title: PlayFab Multiplayer getting started for Unity author: victorku -description: Quickstart for Azure PlayFab Multiplayer Unity plugin. +description: Quickstart for PlayFab Multiplayer Unity plugin. ms.author: victorku ms.date: 11/23/2021 ms.topic: article diff --git a/playfab-docs/multiplayer/lobby/lobby-properties.md b/playfab-docs/multiplayer/lobby/lobby-properties.md index 5fd575953..b1fb5f106 100644 --- a/playfab-docs/multiplayer/lobby/lobby-properties.md +++ b/playfab-docs/multiplayer/lobby/lobby-properties.md @@ -1,5 +1,5 @@ --- -title: Azure PlayFab Lobby custom properties +title: PlayFab Lobby custom properties author: joannaleecy description: Learn about custom properties in Lobby. ms.author: jenelleb @@ -15,34 +15,34 @@ ms.localizationpriority: medium This article describes custom properties stored on the lobby. Use this functionality to store metadata about the game sessions that your lobby's represent. -## Pre-defined properties +## Predefined properties -Each lobby has a set of pre-defined properties commonly needed for most game scenarios. +Each lobby has a set of predefined properties commonly needed for most game scenarios. | Property | Definition | |--------------|-------------------| -| lobbyId | This is the unique identifier for a lobby. It can be used to distinguish between multiple lobbies that a player may be a part of. | -| connectionString | The identifier used to join the lobby. It is provided by the Lobby service. When an invite is sent to other players, the __connectionString__ is sent as the invitation. | +| lobbyId | This is the unique identifier for a lobby. It can be used to distinguish between multiple lobbies that a player might be a part of. | +| connectionString | The identifier used to join the lobby. It's provided by the Lobby service. When an invite is sent to other players, the __connectionString__ is sent as the invitation. | | maxMemberCount | The maximum number of players allowed in the lobby. This property can only be changed by owner. | -| owner | The entity that owns the lobby. Some lobbies may temporarily be ownerless in some circumstances. To learn more, see [Ownership changes](ownership-changes.md). | -| ownerMigrationPolicy | Policy determines how a new owner will be chosen. To learn more, see [Ownership changes](ownership-changes.md). | +| owner | The entity that owns the lobby. Some lobbies might be temporarily ownerless in some circumstances. To learn more, see [Ownership changes](ownership-changes.md). | +| ownerMigrationPolicy | Policy determines how a new owner is chosen. To learn more, see [Ownership changes](ownership-changes.md). | | accessPolicy | Policy indicates who can discover the lobby's connection string. This property can only be changed by the owner. | -| membershipLock | This value indicates whether new members may join the lobby or not. When __Locked__, new members may not join. When __Unlocked__ new members may join. This property can only be changed by the owner. | +| membershipLock | This value indicates whether new members can join the lobby or not. When __Locked__, new members can't join. When __Unlocked__ new members can join. This property can only be changed by the owner. | | RestrictInvitesToLobbyOwner | A setting that controls whether only the lobby owner can send invites to join the lobby. When true, only the lobby owner can send invites. When false or not specified, any member can send invites. Defaults to false if not specified. Restricted to client owned lobbies.| ## Custom Properties -There are 3 types of custom properties that titles can define. +There are three types of custom properties that titles can define. 1. Custom lobby properties * These properties apply to the whole lobby. * Only members of the lobby can see these properties. * Only the owner of the lobby can change these properties. 2. Custom member properties - * There is a unique map of member properties for each member in the lobby + * There's a unique map of member properties for each member in the lobby * Only members of the lobby can see these properties. * All members of the lobby can see every other members' properties. - * Each member may modify their own member properties but cannot modify another member's properties. + * Each member may modify their own member properties but can't modify another member's properties. * Once a member leaves the lobby, their member properties are deleted from the lobby. 3. Custom search properties. * These are special properties which can be used by all players in your title to search for lobbies matching a specific criteria. diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies.md index 72f58d7ea..a12fbddd2 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies.md @@ -31,7 +31,7 @@ The handle of the PFMultiplayer API instance. **`searchingEntity`**   [PFEntityKey*](../../pfmultiplayer/pfentitykey_clientsdk.md) -The playfab entity performing the search. +The PlayFab entity performing the search. **`searchConfiguration`**   [PFLobbySearchConfiguration*](../structs/pflobbysearchconfiguration.md) diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md index 0fba0672e..4e032f1ff 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md @@ -36,8 +36,8 @@ ms.date: 11/15/2023 | [PFMatchmakingMatchMember](structs/pfmatchmakingmatchmember.md) | A member of a match result. | | [PFMatchmakingServerBackfillTicketConfiguration](structs/pfmatchmakingserverbackfillticketconfiguration.md) | Defines the configuration for a server backfill ticket. | | [PFMatchmakingTicketConfiguration](structs/pfmatchmakingticketconfiguration.md) | Defines the configuration for a matchmaking ticket. | -| [PFMultiplayerPort](structs/pfmultiplayerport.md) | A port used by a Playfab Multiplayer Server. | -| [PFMultiplayerServerDetails](structs/pfmultiplayerserverdetails.md) | Details about a Playfab Multiplayer Server. | +| [PFMultiplayerPort](structs/pfmultiplayerport.md) | A port used by a PlayFab Multiplayer Server. | +| [PFMultiplayerServerDetails](structs/pfmultiplayerserverdetails.md) | Details about a PlayFab Multiplayer Server. | ## State changes diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerport.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerport.md index dd5e35fc2..0d3b802e3 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerport.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerport.md @@ -1,7 +1,7 @@ --- author: ScottMunroMS title: "PFMultiplayerPort" -description: "A port used by a Playfab Multiplayer Server." +description: "A port used by a PlayFab Multiplayer Server." ms.author: scmunro ms.topic: reference ms.service: azure-playfab @@ -10,7 +10,7 @@ ms.date: 08/16/2022 # PFMultiplayerPort -A port used by a Playfab Multiplayer Server. +A port used by a PlayFab Multiplayer Server. ## Syntax diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails.md index 5fc72cf74..90bed0ce8 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails.md @@ -1,7 +1,7 @@ --- author: ScottMunroMS title: "PFMultiplayerServerDetails" -description: "Details about a Playfab Multiplayer Server." +description: "Details about a PlayFab Multiplayer Server." ms.author: scmunro ms.topic: reference ms.service: azure-playfab @@ -10,7 +10,7 @@ ms.date: 08/16/2022 # PFMultiplayerServerDetails -Details about a Playfab Multiplayer Server. +Details about a PlayFab Multiplayer Server. ## Syntax @@ -29,12 +29,12 @@ struct PFMultiplayerServerDetails { **`fqdn`**   const char* *is null-terminated* -The fully qualified domain name of the virtual machine that is hosting this multiplayer server. +The fully qualified domain name of the virtual machine that's hosting this multiplayer server. **`ipv4Address`**   const char* *is null-terminated* -The IPv4 address of the virtual machine that is hosting this multiplayer server. +The IPv4 address of the virtual machine that's hosting this multiplayer server. **`ports`**   const [PFMultiplayerPort](pfmultiplayerport.md)* diff --git a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort.md b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort.md index a5e64037c..f5dfe9cdd 100644 --- a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort.md +++ b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort.md @@ -10,7 +10,7 @@ ms.date: 08/18/2022 # Class MultiplayerPort -A port used by a Playfab Multiplayer Server. +A port used by a PlayFab Multiplayer Server. ```csharp public class MultiplayerPort @@ -20,7 +20,7 @@ public class MultiplayerPort | name | description | | --- | --- | -| [MultiplayerPort](MultiplayerPort/MultiplayerPort.md)(…) | A port used by a Playfab Multiplayer Server. | +| [MultiplayerPort](MultiplayerPort/MultiplayerPort.md)(…) | A port used by a PlayFab Multiplayer Server. | | [Name](MultiplayerPort/Name.md) { get; set; } | The name of the port as specified in the PlayFab Game Manager server settings. | | [Num](MultiplayerPort/Num.md) { get; set; } | The number for the port. | | [Protocol](MultiplayerPort/Protocol.md) { get; set; } | The protocol for the port. | diff --git a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort/MultiplayerPort.md b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort/MultiplayerPort.md index 35ac2a1ad..82ce29cb9 100644 --- a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort/MultiplayerPort.md +++ b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort/MultiplayerPort.md @@ -10,7 +10,7 @@ ms.date: 08/18/2022 # MultiplayerPort constructor -A port used by a Playfab Multiplayer Server. +A port used by a PlayFab Multiplayer Server. ```csharp public MultiplayerPort(string name, uint num, MultiplayerProtocolType protocolType) diff --git a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails.md b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails.md index d1f0e45dd..a4c011004 100644 --- a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails.md +++ b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails.md @@ -10,7 +10,7 @@ ms.date: 08/18/2022 # Class MultiplayerServerDetails -Details about a Playfab Multiplayer Server. +Details about a PlayFab Multiplayer Server. ```csharp public class MultiplayerServerDetails @@ -20,9 +20,9 @@ public class MultiplayerServerDetails | name | description | | --- | --- | -| [MultiplayerServerDetails](MultiplayerServerDetails/MultiplayerServerDetails.md)(…) | Details about a Playfab Multiplayer Server. | -| [Fqdn](MultiplayerServerDetails/Fqdn.md) { get; set; } | The fully qualified domain name of the virtual machine that is hosting this multiplayer server. | -| [Ipv4Address](MultiplayerServerDetails/Ipv4Address.md) { get; set; } | The IPv4 address of the virtual machine that is hosting this multiplayer server. | +| [MultiplayerServerDetails](MultiplayerServerDetails/MultiplayerServerDetails.md)(…) | Details about a PlayFab Multiplayer Server. | +| [FQDN](MultiplayerServerDetails/Fqdn.md) { get; set; } | The fully qualified domain name of the virtual machine that's hosting this multiplayer server. | +| [Ipv4Address](MultiplayerServerDetails/Ipv4Address.md) { get; set; } | The IPv4 address of the virtual machine that's hosting this multiplayer server. | | [Ports](MultiplayerServerDetails/Ports.md) { get; set; } | The ports the multiplayer server uses. | | [Region](MultiplayerServerDetails/Region.md) { get; set; } | The server's region. | diff --git a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails/MultiplayerServerDetails.md b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails/MultiplayerServerDetails.md index da7eb5f70..b87c27700 100644 --- a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails/MultiplayerServerDetails.md +++ b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails/MultiplayerServerDetails.md @@ -10,7 +10,7 @@ ms.date: 08/18/2022 # MultiplayerServerDetails constructor -Details about a Playfab Multiplayer Server. +Details about a PlayFab Multiplayer Server. ```csharp public MultiplayerServerDetails(string fqdn, string ipv4Address, IList ports, @@ -19,8 +19,8 @@ public MultiplayerServerDetails(string fqdn, string ipv4Address, IList [!NOTE] > Our SDKs undergo internal testing before every release to ensure the expected level of functionality and normally don't require logging to be enabled by default, particularly in the shipping version of your game. > -> However, sometimes it may be needed to capture and share produced logs with Microsoft for troubleshooting and diagnostic purposes. +> However, sometimes it might be needed to capture and share produced logs with Microsoft for troubleshooting and diagnostic purposes. -The type of logs and the way logging should be configured/captured depends on a platform. Our middleware SDKs (Unity and Unreal) use Party C++ SDKs as an underlying dependency component, and a process of configuring/capturing logs for them is the same or very similar to the process for a corresponding C++ SDK. All necessary instructions and pointers are listed in the table below: +The type of logs and the way logging should be configured/captured depends on a platform. Our middleware SDKs (Unity and Unreal) use Party C++ SDKs as an underlying dependency component, and a process of configuring/capturing logs for them is the same or similar to the process for a corresponding C++ SDK. All necessary instructions and pointers are listed in the table below: ## Per platform logging instructions @@ -27,7 +27,7 @@ The type of logs and the way logging should be configured/captured depends on a |------------|------------|------------| | Android | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `Android` in a table under that section. | | iOS | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `iOS` in a table under that section. | -| MacOS | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `macOS` in a table under that section. | +| macOS | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `macOS` in a table under that section. | | Linux | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `Linux` in a table under that section. | | Switch | Plain text | See `Logging` section of `README.md` file included in a NuGet package for this SDK. | | PlayStation 4 | Plain text | See `Logging` section of `README.md` file included in a NuGet package for this SDK. | diff --git a/playfab-docs/multiplayer/networking/party-playstream-events.md b/playfab-docs/multiplayer/networking/party-playstream-events.md index 37784903e..84d425694 100644 --- a/playfab-docs/multiplayer/networking/party-playstream-events.md +++ b/playfab-docs/multiplayer/networking/party-playstream-events.md @@ -1,6 +1,6 @@ --- title: PlayFab Party PlayStream Events -description: Microsoft Azure PlayFab PlayStream events generated by the Party real-time chat and data communication API. +description: Microsoft PlayFab PlayStream events generated by the Party real-time chat and data communication API. author: joannaleecy ms.author: jenelleb ms.date: 08/16/2019 diff --git a/playfab-docs/multiplayer/networking/party-samples.md b/playfab-docs/multiplayer/networking/party-samples.md index e66836897..a38fb82fc 100644 --- a/playfab-docs/multiplayer/networking/party-samples.md +++ b/playfab-docs/multiplayer/networking/party-samples.md @@ -1,7 +1,7 @@ --- title: Party samples author: joannaleecy -description: Learn about the samples for Azure PlayFab Party. +description: Learn about the samples for PlayFab Party. ms.author: jenelleb ms.date: 10/13/2020 ms.topic: article @@ -12,7 +12,7 @@ ms.localizationpriority: medium # Party samples -This topic lists all the Azure PlayFab Party samples that are currently available. +This topic lists all the PlayFab Party samples that are currently available. If there's a specific sample that you'd like to have, let us know by writing a post on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/multiplayer/networking/party-sdks.md b/playfab-docs/multiplayer/networking/party-sdks.md index b645d853c..7f75e62c5 100644 --- a/playfab-docs/multiplayer/networking/party-sdks.md +++ b/playfab-docs/multiplayer/networking/party-sdks.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Party SDKs +title: PlayFab Party SDKs author: joannaleecy -description: Learn about the SDKs for Azure PlayFab Party. +description: Learn about the SDKs for PlayFab Party. ms.author: jenelleb ms.date: 02/22/2021 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, networking, party, sdk, sample ms.localizationpriority: medium --- -# Azure Playfab Party SDKs +# PlayFab Party SDKs -This topic describes all the Azure PlayFab Party SDKs that are currently available. +This topic describes all the PlayFab Party SDKs that are currently available. If you don't find what you need, let us know by writing a post on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md index 1776e3198..2793b06dd 100644 --- a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md +++ b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md @@ -11,7 +11,7 @@ keywords: playfab, multiplayer, networking, unreal, unreal engine, unreal engine # QuickStart: PlayFab Online Subsystem -This article helps you set up and use Azure PlayFab Multiplayer features like Lobby, Matchmaking, and Party for games built with Unreal Engine 4 or Unreal Engine 5. For the full list of supported platforms and versions in Unreal Engine 4 or Unreal Engine 5, see [Supported platforms](party-unreal-engine-oss-overview.md). +This article helps you set up and use PlayFab Multiplayer features like Lobby, Matchmaking, and Party for games built with Unreal Engine 4 or Unreal Engine 5. For the full list of supported platforms and versions in Unreal Engine 4 or Unreal Engine 5, see [Supported platforms](party-unreal-engine-oss-overview.md). After following the relevant steps that are outlined in this page for your target platforms, you'll be ready to start using the PlayFab Online Subsystem (PF OSS). Authentication, networking, VOIP, grouping into lobbies, and matchmaking is handled on your behalf with no other changes required. diff --git a/playfab-docs/multiplayer/networking/release-notes.md b/playfab-docs/multiplayer/networking/release-notes.md index f18730d59..04e85e45b 100644 --- a/playfab-docs/multiplayer/networking/release-notes.md +++ b/playfab-docs/multiplayer/networking/release-notes.md @@ -13,10 +13,10 @@ ms.localizationpriority: medium # PlayFab Party Release Notes > [!NOTE] -> Support for the XDK and Windows 7 platforms ended on August 1, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using Windows 7 or XDK versions of the PlayFab Party library. +> Support for the Xbox Development Kit (XDK) and Windows 7 platforms ended on August 1, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using Windows 7 or XDK versions of the PlayFab Party library. > [!NOTE] -> Support for 32-bit Android platforms (arm7 and x86) ended on October 19th, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using the PlayFab Party library on 32-bit Android platforms. +> Support for 32-bit Android platforms (arm7 and x86) ended on October 19, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using the PlayFab Party library on 32-bit Android platforms. ## 1.10.16 @@ -33,13 +33,13 @@ February 2, 2026 December 17, 2025 -- Nintendo Switch 2: Added 10 second timeout for webrequests. +- Nintendo Switch 2: Added 10 second timeout for web requests. ## 1.10.14 December 9, 2025 -- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has actually expired. +- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has expired. - Android: Added support for 16 KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). @@ -54,7 +54,7 @@ October 14, 2025 October 6, 2025 -- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has actually expired. +- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has expired. - Android: Added support for 16 KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). - Apple: Added support for Arm64 simulator builds on iOS. @@ -75,28 +75,28 @@ March 11, 2025 January 24, 2025 -- PlayStation®4 and, PlayStation®5: Resolved a crash related to profanity masking on PlayStation platforms. +- PlayStation®4 and PlayStation®5: Resolved a crash related to profanity masking on PlayStation platforms. ## 1.10.6 December 10, 2024 -- PlayStation®4 and, PlayStation®5: Resolved build warnings and errors for integration with C++14 and above. +- PlayStation®4 and PlayStation®5: Resolved build warnings and errors for integration with C++14 and later versions. ## 1.10.5 November 18, 2024 -- Fixed an issue where voice chat would sometimes not work for users remaining in a Party network after other users rejoined and left multiple times. +- Fixed an issue where voice chat sometimes didn't work for users who stayed in a Party network after other users rejoined and left multiple times. - Fixed an issue where [PartyLocalEndpoint::GetEndpointStatistics](reference/classes/PartyLocalEndpoint/methods/partylocalendpoint_getendpointstatistics.md) would report incorrect values for [PartyEndpointStatistic::CurrentlyQueuedSendMessages](reference/enums/partyendpointstatistic.md) and [PartyEndpointStatistic::CurrentlyQueuedSendMessageBytes](reference/enums/partyendpointstatistic.md) when used with direct peer connections. -- Fixed broken symlinks for the framework on the macOS. -- Improved handling log exceptions for non Windows platforms during collection of SDK logs. +- Fixed broken symlinks for the framework on macOS. +- Improved handling of log exceptions for non-Windows platforms during collection of SDK logs. ## 1.10.4 November 12, 2024 -- PlayStation®4 and, PlayStation®5: Resolved crashes related to mutex operations and endpoint state changes during creation and destruction. +- PlayStation®4 and PlayStation®5: Resolved crashes related to mutex operations and endpoint state changes during creation and destruction. ## 1.10.3 @@ -114,27 +114,27 @@ September 18, 2024 ### Bug fixes -- Fixed an issue where the library may crash when establishing direct peer connections in networks with three or more devices. +- Fixed an issue where the library might crash when it establishes direct peer connections in networks with three or more devices. ## 1.10.0 August 5, 2024 -- Added support for game_server entities, so servers can connect to Party networks via the SDK and be securely identified by game clients. After authenticating a `game_server` entity via AuthenticateGameServerWithCustomId, it can be added as a local user via [PartyManager::CreateLocalUserWithEntityType](reference/classes/PartyManager/methods/partymanager_createlocaluserwithentitytype.md). +- Added support for `game_server` entities, so servers can connect to Party networks via the SDK and be securely identified by game clients. After authenticating a `game_server` entity via `AuthenticateGameServerWithCustomId`, it can be added as a local user via [PartyManager::CreateLocalUserWithEntityType](reference/classes/PartyManager/methods/partymanager_createlocaluserwithentitytype.md). - Added methods for determining the entity type associated with each entity in the library. For more information, see [PartyLocalUser::GetEntityType](reference/classes/PartyLocalUser/methods/partylocaluser_getentitytype.md), [PartyEndpoint::GetEntityType](reference/classes/PartyEndpoint/methods/partyendpoint_getentitytype.md), and [PartyChatControl::GetEntityType](reference/classes/PartyChatControl/methods/partychatcontrol_getentitytype.md). - Added a direct peer connectivity option that enables direct peer connections between `title_player` and `game_server` entities while disallowing direct peer connections between `title_player` entities and other `title_player` entities. For more information, see [PartyDirectPeerConnectivityOptions::OnlyServers](reference/enums/partydirectpeerconnectivityoptions.md). - Added methods to retrieve a convenient list of endpoints based on filters. For more information, see [PartyNetwork::GetEndpointsByUserType](reference/classes/PartyNetwork/methods/partynetwork_getendpointsbyusertype.md). -- Memory allocations by third party libraries used in PlayFab Party on PlayStation®4 and, PlayStation®5 that were using default allocators have been updated to use Party's memory callbacks. Titles using [PartyManager::SetMemoryCallbacks](reference/classes/PartyManager/methods/partymanager_setmemorycallbacks.md) to configure title-specific memory allocation functions allocations will now see and have control over these allocations. +- Updated memory allocations by third party libraries used in PlayFab Party on PlayStation®4 and, PlayStation®5 that were using default allocators have been updated to use Party's memory callbacks. Titles using [PartyManager::SetMemoryCallbacks](reference/classes/PartyManager/methods/partymanager_setmemorycallbacks.md) to configure title-specific memory allocation functions allocations will now see and have control over these allocations. ### Bug fixes -- Fixed an issue where the library may crash on Windows or Xbox while the process is terminating. +- Fixed an issue where the library might crash on Windows or Xbox while the process is terminating. - Addressed spurious direct peer connection failures after a previous connection attempt failed in certain cases for non Windows platforms. -- Fixed an issue where the DestroyNetwork event was not fired during repeated Party network creation and destroying. +- Fixed an issue where the DestroyNetwork event wasn't fired during repeated Party network creation and destroying. ### Known issues -- The library may occasionally crash when establishing direct peer connections in networks with three or more devices. +- The library might occasionally crash when establishing direct peer connections in networks with three or more devices. ## 1.9.5 @@ -177,13 +177,13 @@ February 5, 2024 November 13, 2023 -- Fixed a bug where a crash may occur when a client tries to leave a network on Nintendo Switch. +- Fixed a bug where a crash might occur when a client tries to leave a network on Nintendo Switch. ## 1.8.10 October 19, 2023 -This release updates the minimum SDK versioning and target SDK versioning for PlayFab Party Apple and Android platforms. +This release updates the minimum SDK version and target SDK version for PlayFab Party Apple and Android platforms. For Apple platforms, we follow [Apple's Xcode guidelines](https://developer.apple.com/support/xcode/) with the release of Xcode 15. - iOS @@ -210,7 +210,7 @@ October 20, 2023 - Implemented shared properties for endpoints. Shared properties may be set when creating an endpoint via [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md). A shared property may be retrieved using [`PartyEndpoint::GetSharedProperty`](reference/classes/PartyEndpoint/methods/partyendpoint_getsharedproperty.md). -- Improved audio packet queueing to reduce perceived chat audio latency in some scenarios. +- Improved audio packet queuing to reduce perceived chat audio latency in some scenarios. - Upgraded internal version of the Opus codec. - Fixed a low frequency crash. - Improved internal diagnostics. @@ -226,7 +226,7 @@ June 28, 2023 ### Bug fixes -- Fixed a bug where [`PartyLocalChatControl::SetAudioRenderVolume`](reference/classes/PartyLocalChatControl/methods/partylocalchatcontrol_setaudiorendervolume.md) would not properly work for Nintendo Switch, PlayStation®4 and, PlayStation®5. +- Fixed a bug where [`PartyLocalChatControl::SetAudioRenderVolume`](reference/classes/PartyLocalChatControl/methods/partylocalchatcontrol_setaudiorendervolume.md) didn't work properly for Nintendo Switch, PlayStation®4, and PlayStation®5. “PlayStation” is a registered trademark or trademark of Sony Interactive Entertainment Inc. @@ -251,7 +251,7 @@ May 8, 2023 - iOS, Android: Added support for enabling noise suppression on audio captured from a local chat control. For more information, see [`PartyLocalChatControl::SetVoiceAudioOptions`](reference/classes/PartyLocalChatControl/methods/partylocalchatcontrol_setvoiceaudiooptions.md). ### Bug fixes -- Fixed a bug where the library may leak memory due to internal diagnostic tracking when the user's entity token expires. +- Fixed a bug where the library could leak memory due to internal diagnostic tracking when the user's entity token expires. ## 1.7.23 @@ -264,8 +264,8 @@ April 1, 2023 March 30, 2023 ### Bug fixes -- Fixed a bug where Party could crash if it was not cleaned up before the host process started exiting. -- Changed behavior for peer-to-peer connection to fallback to a relayed connection if the link is disconnected unexpectedly. The previous behavior would disconnect both the devices from the network. +- Fixed a bug where Party could crash if it wasn't cleaned up before the host process started exiting. +- Changed behavior for peer-to-peer connection to fallback to a relayed connection if the link is disconnected unexpectedly. The previous behavior disconnected both devices from the network. ## 1.7.20 @@ -273,7 +273,7 @@ February 8, 2023 ### Bug fixes -- Fixed a bug where audio from 44.1 kHz microphones may sound distorted. +- Fixed a bug where audio from 44.1-kHz microphones might sound distorted. - Improved diagnostic error messages for network errors reported by [PartyManager::GetErrorMessage()](reference/classes/PartyManager/methods/partymanager_geterrormessage.md). ## 1.7.19 @@ -290,8 +290,8 @@ October 7, 2022 ### Bug fixes -- Fixed a bug where a crash may occur when a chat control is connect to a network on iOS. -- Fixed a bug where a crash may occur when enabling iOS log. +- Fixed a bug where a crash might occur when a chat control is connected to a network on iOS. +- Fixed a bug where a crash might occur when enabling iOS log. ## 1.7.16 @@ -302,7 +302,7 @@ September 27, 2022 - Added .bundle for Unity plug-in loading and native macOS development. ### Bug fixes -- Fixed a bug where a crash may occur when enabling macOS log. +- Fixed a bug where a crash might occur when enabling macOS log. ## 1.7.14 @@ -310,7 +310,7 @@ August 12, 2022 ### New SDKs for Linux and macOS -- Added native support for PlayFab Party on Linux and macOS, enabling game developers to create cross-platform or multiplatform real-time multiplayer experiences on even more platforms. For links to these and other SDK releases,see [Azure Playfab Party SDKs](party-sdks.md). +- Added native support for PlayFab Party on Linux and macOS, enabling game developers to create cross-platform or multiplatform real-time multiplayer experiences on even more platforms. For links to these and other SDK releases, see [PlayFab Party SDKs](party-sdks.md). August 11, 2022 @@ -353,8 +353,8 @@ February 8, 2022 September 30, 2021 ### Bug fixes -- Fixed an issue where some 16kHz microphones weren't working. -- Fixed an issue where microphone permission changes were not handled on Windows. +- Fixed an issue where some 16 kHz microphones weren't working. +- Fixed an issue where microphone permission changes weren't handled on Windows. - Fixed a memory leak in some `PartyManager::CreateNewNetwork()` failure conditions. - Fixed an occasional crash in `PartyLocalEndpoint::GetEndpointStatistics()`. @@ -374,13 +374,13 @@ June 29, 2021 ### Bug fixes -- Fixed a bug where a crash may occur when a chat control is connected to a network while that same chat control is disconnecting from another network. +- Fixed a bug where a crash might occur when a chat control connects to a network while that same chat control is disconnecting from another network. ## 1.6.0 April 12, 2021 ### New thread control and text moderation features -- The library's work can now be run manually on game-controlled threads. For more information, see [`PartyManager::SetWorkMode`](reference/classes/PartyManager/methods/partymanager_setworkmode.md). +- The library's work can now run manually on game-controlled threads. For more information, see [`PartyManager::SetWorkMode`](reference/classes/PartyManager/methods/partymanager_setworkmode.md). - Offensive text chat can now optionally be filtered. For more information, see [Using text moderation](../../community/voice-communications/concepts-text-moderation.md). ### Explicit enum numbering in the header @@ -391,26 +391,27 @@ April 12, 2021 March 26, 2021 ### Bug fixes -- Fixed a bug where audio is cutting out on iOS devices using Bluetooth headsets. +- Fixed a bug where audio cuts out on iOS devices using Bluetooth headsets. - Fixed a bug where an incorrect error code is generated when the app doesn't have permission to activate a microphone on Windows platforms. -- Fixed a bug where an unhealthy device is never refreshed unless something else forces a refresh. -- Fixed a bug where a crash may occur when dereferencing a send channel's user data after the source endpoint associated with that channel has become invalid. +- Fixed a bug where an unhealthy device isn't refreshed unless something else forces a refresh. +- Fixed a bug where a crash might occur when dereferencing a send channel's user data after the source endpoint associated with that channel becomes invalid. - Fixed a bug where clients experience silent failures if a remote chat control doesn't have a language code. ## 1.5.10 ### Bug fixes -- Fixed a bug where the library may fail to initialize on some Windows devices due to a mismatch between the processor affinity of the process and the library's default thread affinity. -- Fixed a bug where the library may not provide errors when an operation fails due to an internal web request failure. -- Fixed a bug where a crash may occur when direct peer connectivity is enabled and the library attempts to establish direct peer connectivity to another device. -- Fixed a bug that may result in crackling or distorted audio. +- Fixed a bug where the library might fail to initialize on some Windows devices due to a mismatch between the processor affinity of the process and the library's default thread affinity. +- Fixed a bug where the library might not provide errors when an operation fails due to an internal web request failure. +- Fixed a bug where a crash might occur when direct peer connectivity is enabled and the library attempts to establish direct peer connectivity to another device. +- Fixed a bug that might result in crackling or distorted audio. ## 1.5.1 September 05, 2020 + ### Bug fix -- Fixed a bug where the library may fail to activate the microphone on iOS. +- Fixed a bug where the library fails to activate the microphone on iOS. ## 1.5.0 @@ -438,7 +439,7 @@ April 30, 2020 - The transcription stack has been updated to use TLS1.2 on Windows 7, Android, and iOS. Upgrade if you make use of any of these platforms as TLS1.1 support will be deprecated by [Azure Speech Services](https://azure.microsoft.com/updates/azuretls12/) beginning in September 2020. All other platforms already support TLS1.2 and no upgrade is necessary. ### Bug fixes -- Fixed a bug where the `languageCode` field in the `PartyCreateChatControlCompletedStateChange` struct was not being populated. +- Fixed a bug where the `languageCode` field in the `PartyCreateChatControlCompletedStateChange` struct wasn't being populated. - Fixed a bug that was artificially inflating the latency measurements reported by `PartyManager::GetRegions()`. - Fixed a bug that allowed `PartyManager::SetMemoryCallbacks()` to be called at unsafe times. - Fixed a bug where calling `PartyManager::DestroyLocalUser()` with a `PartyLocalUser` in a `PartyNetwork` would generate a `PartyLocalUserRemovedStateChange` with an incorrect value in the removedReason field, `PartyLocalUserRemovedReason::RemoveLocalUser`, instead of the correct value, `PartyLocalUserRemovedReason::DestroyLocalUser`. @@ -451,12 +452,12 @@ April 30, 2020 - Typos in the header documentation have been fixed. - A more descriptive error code and error message are now provided when an invalid region is passed to `PartyManager::CreateNewNetwork()`. - The documentation for the lifetimes of `PartyString` values has been clarified for the structures and interfaces in Party.h. -- The documentation for `PartyManager::Cleanup()` was clarified to explain it is not a thread-safe call. +- The documentation for `PartyManager::Cleanup()` was clarified to explain it isn't a thread-safe call. - A more descriptive error code and error message are provided when `PartyManager::ConnectToNetwork()` asynchronously fails with internet connectivity errors. ## 1.3.0 -### Chat API Changes +### Chat API changes * The real-time audio manipulation functions, which can be used to modify outgoing or incoming voice chat audio, are implemented for Windows and Xbox. For more information, see [Using real-time audio manipulation to apply custom voice effects](../../community/voice-communications/concepts-realtime-audio-manipulation.md). * The chat permission options have more options for optionally configuring text-to-speech and microphone audio permissions independently. For more information, see [`PartyChatPermissionOptions`](reference/enums/partychatpermissionoptions.md). @@ -466,24 +467,24 @@ April 30, 2020 ## 1.2.2 -### iOS Changes +### iOS changes - Adds support for the volume control API. ## 1.2.0 -### Android Changes +### Android changes - Adds support for the volume control API. -- Removes audio focus handling from the library. Host applications are now expected to implement their own focus handling logic. +- Removes audio focus handling from the library. Host applications are now expected to implement their own focus handling logic. ## 1.0.2 -- Fixed crash in background telemetry +- Fixed crash in background telemetry. ## 1.0.1 -### Party API Changes +### Party API changes #### PartyManager::SetMemoryCallbacks Changes @@ -495,27 +496,27 @@ The `PartyStateChangeResult` value `TitleCreateNetworkThrottled` has been remove ## 0.7.0-prerelease -### Windows Packaging Changes +### Windows packaging changes This release of Party introduces a new NuGet package, [Microsoft.PlayFab.PlayFabParty.Cpp.Windows](https://www.nuget.org/packages/Microsoft.PlayFab.PlayFabParty.Cpp.Windows), which replaces and deprecates the NuGet packages specific to Windows 10 and Windows 7 (Microsoft.PlayFab.PlayFabParty.Cpp.Win10 and Microsoft.PlayFab.PlayFabParty.Cpp.Win7, respectively). The new unified Windows NuGet package contains two new DLLs, PartyWin.dll (supports Windows 8.1 and up) and PartyWin7.dll (only for use on Windows 7). With the new Windows unified NuGet package, the correct Party DLL is loaded based on runtime detection of the OS version, so both PartyWin.dll and PartyWin7.dll should be included in the game distribution package. -### Android Changes +### Android changes The Android flavor now uses a shared object for Party (libparty.so) instead of a static library (libparty.a). This release also contains Android-specific bug fixes for audio device selection. -### iOS Changes +### iOS changes The iOS flavor of Party now has the framework package included for dynamically loading libparty instead of the statically built libparty.a. -### API Changes +### API changes #### UpdateEntityToken API This release of Party makes a change related to the handling of PlayFab entity tokens. In the previous version, the game provided Party with a user's entity token in the `PartyManager::CreateLocalUser()` API. Thereafter, Party internally refreshed the entity token and kept it up to date. -In this version, the internal token refreshing behavior has been removed and replaced by a new API, `PartyLocalUser::UpdateEntityToken()`. The caller is now responsible for monitoring the expiration of the entity token provided to `PartyManager::CreateLocalUser()` and `PartyLocalUser::UpdateEntityToken()`. When the token is nearing or past the expiration time, a new token should be obtained by performing a PlayFab login operation and provided to the Party library by calling `PartyLocalUser::UpdateEntityToken()`. It is recommended to acquire a new token when the previously supplied token is halfway through its validity period. On platforms that may enter a low power state or pause application execution for a long time, the token may be prevented from being refreshed before it expires. The token should be checked for expiration once execution resumes. +In this version, the internal token refreshing behavior has been removed and replaced by a new API, `PartyLocalUser::UpdateEntityToken()`. The caller is now responsible for monitoring the expiration of the entity token provided to `PartyManager::CreateLocalUser()` and `PartyLocalUser::UpdateEntityToken()`. When the token is nearing or past the expiration time, a new token should be obtained by performing a PlayFab login operation and provided to the Party library by calling `PartyLocalUser::UpdateEntityToken()`. It's recommended to acquire a new token when the previously supplied token is halfway through its validity period. On platforms that enter a low power state or pause application execution for a long time, the token might be prevented from being refreshed before it expires. The token should be checked for expiration once execution resumes. The rough flow is as follows: @@ -527,14 +528,14 @@ The rough flow is as follows: 1. [New] Call `PartyLocalUser::UpdateEntityToken()` to pass in the new token to Party Additional notes: -- The act of acquiring an entity token does not invalidate any previously obtained entity tokens. They remain valid until they expire. +- The act of acquiring an entity token doesn't invalidate any previously obtained entity tokens. They remain valid until they expire. - The internal refreshing functionality was removed because most games are expected to make their own PlayFab calls. Having both the game and the Party library fetch entity tokens causes unnecessary service load to manage two sets of tokens. #### Chat API Changes The `PartyVoiceChatTranscriptionReceivedStateChange` now includes a `languageCode` field, which indicates the language of the transcription. -The `PartyChatTextReceivedStateChange` now includes a `languageCode` field, which may indicate the language of the chat text. The `languageCode` field will be populated when chat text translation has been enabled via `PartyLocalChatControl::SetTextChatOptions()`. +The `PartyChatTextReceivedStateChange` now includes a `languageCode` field, which indicates the language of the chat text. The `languageCode` field will be populated when chat text translation has been enabled via `PartyLocalChatControl::SetTextChatOptions()`. ## 0.6.0-prerelease @@ -549,12 +550,12 @@ For more information, see the following links: ## 0.5.0-prerelease -### API Changes +### API changes #### Accessible Chat * Added support for text-to-speech narration. (see `PartyLocalChatControl::SetTextToSpeechProfile()`) * Added more options for controlling when speech-to-text occurs. (see `PartyLocalChatControl::SetTranscriptionOptions()`) -* Added text-to-text translation to the API, although it is not yet supported. (see `PartyLocalChatControl::SetTextChatOptions()`) +* Added text-to-text translation to the API, although it isn't yet supported. (see `PartyLocalChatControl::SetTextChatOptions()`) * Reduced text-to-speech bandwidth and memory usage. #### Network access control @@ -563,13 +564,13 @@ For more information, see the following links: ## 0.4.6-prerelease -### API Changes +### API changes Added new public API `PartyLocalUser::UpdateEntityToken()`. ## 0.2.0-prerelease -### API Changes +### API changes * `PartyManager::Initialize` now requires a valid PlayFab Title ID to be passed in. diff --git a/playfab-docs/multiplayer/networking/unreal-release-notes.md b/playfab-docs/multiplayer/networking/unreal-release-notes.md index 3e5c86045..8e13b6146 100644 --- a/playfab-docs/multiplayer/networking/unreal-release-notes.md +++ b/playfab-docs/multiplayer/networking/unreal-release-notes.md @@ -130,8 +130,8 @@ Known issue: - To invite a Steam or PlayStation player, the host must be on the same platform. ## 2.0.0 -- UE4 engine OSS PlayFab is updated to use Multiplayer features offered by Azure PlayFab such as Lobby, Matchmaking along with PlayFab Party. -This update replaces the Xbox provided MPSD with Azure PlayFab Lobby and XBL Smart match with Azure Matchmaking service. +- UE4 engine OSS PlayFab is updated to use Multiplayer features offered by PlayFab such as Lobby, Matchmaking along with PlayFab Party. +This update replaces the Xbox provided MPSD with PlayFab Lobby and XBL Smart match with Azure Matchmaking service. - XDK is no longer supported for this version of the OSS. ## 1.0.7 diff --git a/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md b/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md index 2e0aaeb36..4f478179a 100644 --- a/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md +++ b/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md @@ -120,7 +120,7 @@ docker build -t customer5555555.azurecr.io/pvp_gameserver:v1 . 4. Upload the container image -Run the below commands to push the image to your Azure PlayFab Container registry. Select a meaningful and helpful name:tag combination for your uploaded container image. Then use [docker push](https://docs.docker.com/engine/reference/commandline/push/) or another container registry client, to upload your container to the Azure PlayFab operated registry. +Run the below commands to push the image to your PlayFab Container registry. Select a meaningful and helpful name:tag combination for your uploaded container image. Then use [docker push](https://docs.docker.com/engine/reference/commandline/push/) or another container registry client, to upload your container to the PlayFab operated registry. ```docker docker tag hello-world customer5555555.azurecr.io/pvp_gameserver:v1 diff --git a/playfab-docs/multiplayer/servers/directly-debugging-game-servers.md b/playfab-docs/multiplayer/servers/directly-debugging-game-servers.md index 528bba36e..d941ff529 100644 --- a/playfab-docs/multiplayer/servers/directly-debugging-game-servers.md +++ b/playfab-docs/multiplayer/servers/directly-debugging-game-servers.md @@ -52,7 +52,7 @@ This information is listed on __docker ps__: For more information, see [Docker networking](https://docs.docker.com/network/). > [!NOTE] -> In both Windows and Linux, Docker containers are part of the "playfab" Docker network. You can do docker inspect network playfab to see information about the network. +> In both Windows and Linux, Docker containers are part of the "playfab" Docker network. Use `docker inspect network playfab` to view information about the PlayFab network. #### How can I see runtime details for a container? diff --git a/playfab-docs/multiplayer/servers/os-patch-updates.md b/playfab-docs/multiplayer/servers/os-patch-updates.md index c2674de8d..3e0cef67e 100644 --- a/playfab-docs/multiplayer/servers/os-patch-updates.md +++ b/playfab-docs/multiplayer/servers/os-patch-updates.md @@ -12,11 +12,11 @@ ms.localizationpriority: medium # OS patch updates for Windows -Playfab Multiplayers Servers managed Windows containers undergo a methodical OS patch update process to ensure game servers are operating with the latest security updates. Each month, Azure Compute certifies a Windows OS image that is integrated into Multiplayer Servers for developers to choose from the "Windows Server Core Preview" toggle during the build creation process. Developers are encouraged to test their non-production game servers built with the "Windows Server Core Preview" option. +PlayFab Multiplayers Servers managed Windows containers undergo a methodical OS patch update process to ensure game servers are operating with the latest security updates. Each month, Azure Compute certifies a Windows OS image that is integrated into Multiplayer Servers for developers to choose from the "Windows Server Core Preview" toggle during the build creation process. Developers are encouraged to test their non-production game servers built with the "Windows Server Core Preview" option. ![Multiplayer - OS Patch Update UX](media/ospatchupdate_ux.png) -After 30 days, Multiplayer Servers will migrate the Windows Server Core Preview to the Windows Server Core image option - signaling a PlayFab approved OS image for production readiness. This process will repeat every 30 days, cycling an OS preview image to its mainline OS core image. If a game server built with OS core version that doesn’t match PlayFab’s OS core version, PlayFab will auto-update your game build server with the latest mainline OS core image. This process is applied automatically with no build changes required by the developer. +After 30 days, Multiplayer Servers will migrate the Windows Server Core Preview to the Windows Server Core image option - signaling a PlayFab approved OS image for production readiness. This process repeats every 30 days, cycling an OS preview image to its mainline OS core image. If a game server built with OS core version that doesn’t match PlayFab’s OS core version, PlayFab will auto-update your game build server with the latest mainline OS core image. This process is applied automatically with no build changes required by the developer. ## Patch update cycle @@ -27,24 +27,24 @@ The following image illustrates the OS patch level update cycle. | Stage | Stakeholder | Description | |---|---|---| -| 1 | Customer | Continuous integration & test process deploys production game builds with OS core and tests game builds with OS preview | +| 1 | Customer | Continuous integration and test process deploys production game builds with OS core and tests game builds with OS preview | | 2 | Azure | MPS validates new published Windows OS patch | | 3 | MPS | PlayFab replaces MPS OS preview with Windows OS patch | | 4 | MPS | PlayFab replaces MPS OS core with MPS OS preview 30-days prior | | 5 | MPS | PlayFab auto-updates game builds with OS Core | -## Best Practices +## Best practices 1. Developers are encouraged to create and test their non-production game server builds with the OS preview image option. -1. Developers with a mature build and continuous integration & deployment process should take into consideration that OS image updates cycle every 30 days +1. Developers with a mature build and continuous integration and deployment process should take into consideration that OS image updates cycle every 30 days ## Constraints 1. The patch update process occurs monthly -1. Developers cannot opt out of the monthly OS patch level updates -1. The patch update process is only applicable to Windows managed containers and does not apply to custom containers or Linux. +1. Developers can't opt out of the monthly OS patch level updates +1. The patch update process is only applicable to Windows managed containers and doesn't apply to custom containers or Linux. > [!NOTE] > -> - Game server builds are immutable once created. Therefore, developers cannot toggle between OS image preview and OS image core. -> - A game server operating in production will be auto-updated to the latest OS core image version if the version that the build was made is older than the latest. This will be applied automatically for any new multiplayer server allocation request only. +> - Game server builds are immutable once created. Therefore, developers can't toggle between OS image preview and OS image core. +> - A game server operating in production will be auto-updated to the latest OS core image version if the version that the build was made is older than the latest. This will be applied automatically for any new multiplayer server allocation request only. diff --git a/playfab-docs/multiplayer/servers/server-samples-resources.md b/playfab-docs/multiplayer/servers/server-samples-resources.md index 654322cde..e74a1b196 100644 --- a/playfab-docs/multiplayer/servers/server-samples-resources.md +++ b/playfab-docs/multiplayer/servers/server-samples-resources.md @@ -1,7 +1,7 @@ --- title: Multiplayer Servers samples and resources author: joannaleecy -description: Samples and resources for Azure PlayFab Multiplayer Game Servers. +description: Samples and resources for PlayFab Multiplayer Game Servers. ms.author: jenelleb ms.date: 04/01/2021 ms.topic: article diff --git a/playfab-docs/multiplayer/servers/server-sdks.md b/playfab-docs/multiplayer/servers/server-sdks.md index 4ff381a1b..499eeec78 100644 --- a/playfab-docs/multiplayer/servers/server-sdks.md +++ b/playfab-docs/multiplayer/servers/server-sdks.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Multiplayer Game Server SDKs +title: PlayFab Multiplayer Game Server SDKs author: joannaleecy -description: Learn about the SDKs for Azure PlayFab Multiplayer Game Servers. +description: Learn about the SDKs for PlayFab Multiplayer Game Servers. ms.author: jenelleb ms.date: 01/21/2021 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, networking, party, sdk, sample ms.localizationpriority: medium --- -# Azure Playfab Multiplayer Game Server SDKs +# PlayFab Multiplayer Game Server SDKs -This topic lists the different flavors of Azure PlayFab Multiplayer Game Server SDKs (GSDKs) we have today. +This topic lists the different flavors of PlayFab Multiplayer Game Server SDKs (GSDKs) we have today. ## Download links diff --git a/playfab-docs/multiplayer/servers/server-terms.md b/playfab-docs/multiplayer/servers/server-terms.md index 656c86097..ed5a38b2a 100644 --- a/playfab-docs/multiplayer/servers/server-terms.md +++ b/playfab-docs/multiplayer/servers/server-terms.md @@ -1,7 +1,7 @@ --- -title: Playfab Multiplayer Server terms +title: PlayFab Multiplayer Server terms author: joannaleecy -description: Playfab Multiplayer Server terms. +description: PlayFab Multiplayer Server terms. ms.author: jenelleb ms.date: 03/10/2021 ms.topic: article @@ -12,18 +12,18 @@ ms.localizationpriority: medium # Terminology -This topic explains the terms used for PlayFab Multiplayer Server. We understand that it can be confusing since the word server is used in multiple places. +This article explains the terms used for PlayFab Multiplayer Server. We understand that it can be confusing since the word server is used in multiple places. -The internal structure of the PlayFab Multiplayer Server and general relationship of the various components is also lightly covered here. For details, see [Basics of a PlayFab game server](basics-of-a-playFab-game-server.md). +The article also briefly covers the internal structure of the PlayFab Multiplayer Server and the general relationship of the various components. For more information, see [Basics of a PlayFab game server](basics-of-a-playFab-game-server.md). ## PlayFab Multiplayer Servers -PlayFab Multiplayer Servers can also be known as PlayFab virtual machines (VMs) and Servers. +PlayFab Multiplayer Servers are also known as PlayFab virtual machines (VMs) and Servers. -They are Azure VMs with PlayFab managed service functionalities. Added functionalities optimize them for use as multiplayer game servers. +They're Azure VMs with PlayFab managed service functionalities. The added functionalities optimize them for use as multiplayer game servers. Each PlayFab VM: -* Has a component known as *PlayFab VM agent*. PlayFab VM agent provides information about your game server's current state, health status, players that are currently connected, and other telemtry. +* Has a component known as *PlayFab VM agent*. PlayFab VM agent provides information about your game server's current state, health status, players that are currently connected, and other telemetry. * Can have multiple containers (game servers) running on them. Containers are a way to wrap up an application into its own isolated package. To learn more, see [What is a container?](https://azure.microsoft.com/overview/what-is-a-container/) ### Game server containers @@ -32,24 +32,24 @@ Game servers run as containerized applications. This means that your game server Each container: * Functions as a game server -* Has a PlayFab Multiplayer Game Server Build. It is your usual game server build that is integrated with the PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must include the GSDK and implement specific methods using APIs in the GSDK. This enables your game server to be connected to the PlayFab VM agent. +* Has a PlayFab Multiplayer Game Server Build. It is your usual game server build that is integrated with the PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must include the GSDK and implement specific methods using APIs in the GSDK. This integration enables your game server to connect to the PlayFab VM agent. -Image below illustrates the various components of a PlayFab Multiplayer Server. +The following image illustrates the various components of a PlayFab Multiplayer Server. ![PlayFab Multiplayer Server components](media/tutorials/multiplayer-server-hosting-service-diagram.png) ## Definition of key terms -* **Game server executable**: This is a game server application that runs in containers of PlayFab VMs. It may be a simple network repeater, a fully authoritative game server running physics and AI, or anything in between. All game server executables needs to be integrated with PlayFab Game Server SDK (GSDK). This allows your game server to be able to interact with the PlayFab Multiplayer platform service. +* **Game server executable**: This term refers to a game server application that runs in containers on PlayFab VMs. It might be a simple network repeater, a fully authoritative game server running physics and AI, or anything in between. All game server executables need to be integrated with PlayFab Game Server SDK (GSDK). By using this SDK, your game server can interact with the PlayFab Multiplayer platform service. -* **Game server build**: This is the full set of content that is uploaded onto the game server. It includes the game server executable packaged with all the assets and certificates needed. It can be uploaded as individual certificates, zip files, and/or a container image. If you don't need a custom container image, you can use PlayFab managed Windows containers. +* **Game server build**: This term refers to the full set of content that you upload onto the game server. It includes the game server executable packaged with all the assets and certificates needed. You can upload it as individual certificates, zip files, and/or a container image. If you don't need a custom container image, you can use PlayFab managed Windows containers. -* **PlayFab Multiplayer Game Server Build**: This is the only type of game server build that can be used in PlayFab Multiplayer Servers. It is your usual game server build (as defined above) that is integrated with the PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must include the GSDK and implement specific methods using APIs in the GSDK. +* **PlayFab Multiplayer Game Server Build**: This term refers to the only type of game server build that you can use in PlayFab Multiplayer Servers. It's your usual game server build (as defined above) that you integrate with the PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must include the GSDK and implement specific methods by using APIs in the GSDK. -* **Game server**: This is your game server executable running in a container. There may be multiple containers (servers) running on a single virtual machine. +* **Game server**: This term refers to your game server executable running in a container. A single virtual machine can run multiple containers (servers). * **PlayFab VM agent**: This agent is built into PlayFab VMs and facilitates key server interactions with the *PlayFab Multiplayer platform service*. The GSDK in the game server executable connects your game server to the PlayFab agent. -* **PlayFab Multiplayer platform service**: Managed service that runs in the background for PlayFab Multiplayer Servers. It communicates information through PlayFab VM agent about your game server's current state, health status, players that are currently connected, and other telemtry. +* **PlayFab Multiplayer platform service**: This managed service runs in the background for PlayFab Multiplayer Servers. It communicates information through the PlayFab VM agent about your game server's current state, health status, players that are currently connected, and other telemetry. ## Next steps diff --git a/playfab-docs/multiplayer/servers/vmstartupscript.md b/playfab-docs/multiplayer/servers/vmstartupscript.md index 5a7a2fa88..edd2a1d0f 100644 --- a/playfab-docs/multiplayer/servers/vmstartupscript.md +++ b/playfab-docs/multiplayer/servers/vmstartupscript.md @@ -17,7 +17,7 @@ ms.localizationpriority: medium > [!Important] > This feature is in preview. You're welcome to start using it today and give us your feedback. Instructions on how to connect with us is provided at the end of the article. Note that technical support is limited during preview. -VmStartupScript allows you to run a custom script on virtual machines (VMs) that are used in Azure PlayFab Multiplayer Servers (MPS). MPS is optimized for game servers hosting, making it easy for your title to scale dynamically according to demand. To improve the ease of customizing a large number of servers quickly during VM initialization, the custom script can run on every underlying VM that hosts your game servers. It can be used to accomplish tasks such as installing custom software, modifying security settings, using a custom service to log game server output and metrics, and more. +VmStartupScript allows you to run a custom script on virtual machines (VMs) that are used in PlayFab Multiplayer Servers (MPS). MPS is optimized for game servers hosting, making it easy for your title to scale dynamically according to demand. To improve the ease of customizing a large number of servers quickly during VM initialization, the custom script can run on every underlying VM that hosts your game servers. It can be used to accomplish tasks such as installing custom software, modifying security settings, using a custom service to log game server output and metrics, and more. > [!Note] > This is an advanced feature that should be used with extreme caution. The running script executes in the Virtual Machine (VM) level with admin (root) privileges. If not used properly, it can potentially disrupt the regular flow of the running game servers, or even prevent them from running at all. The end user is responsible for the content of the script. diff --git a/playfab-docs/player-progression/index.yml b/playfab-docs/player-progression/index.yml index 5034e95fb..ec0692dd9 100644 --- a/playfab-docs/player-progression/index.yml +++ b/playfab-docs/player-progression/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Player progression documentation +title: PlayFab Player progression documentation summary: PlayFab Player Progression services enable reliable storage and sharing of player progression data across all gaming devices. # < 160 chars metadata: diff --git a/playfab-docs/player-progression/statistics/index.md b/playfab-docs/player-progression/statistics/index.md index e7058074a..c2efbd05f 100644 --- a/playfab-docs/player-progression/statistics/index.md +++ b/playfab-docs/player-progression/statistics/index.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Statistics overview +title: PlayFab Statistics overview author: braulioal -description: Learn about Azure PlayFab Statistics. +description: Learn about PlayFab Statistics. ms.author: braulioal ms.date: 09/01/2024 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, leaderboard, stats ms.localizationpriority: medium --- -# Azure PlayFab Statistics overview +# PlayFab Statistics overview -Azure Playfab Statistics is a cross-platform service that enables the numerical representation of player activity within a title. +PlayFab Statistics is a cross-platform service that enables the numerical representation of player activity within a title. ![PlayFab Stats Architecture](media/stats-relationship.png) diff --git a/playfab-docs/pricing/Meters/meters.md b/playfab-docs/pricing/Meters/meters.md index 9487c24c7..63afe42a9 100644 --- a/playfab-docs/pricing/Meters/meters.md +++ b/playfab-docs/pricing/Meters/meters.md @@ -122,7 +122,7 @@ PlayFab Matchmaking and Lobby are highly-customizable, proven solutions for buil ### Leaderboard -Azure Playfab Leaderboards is a cross-platform service that allows to create a sorted list of players with the purpose +PlayFab Leaderboards is a cross-platform service that allows to create a sorted list of players with the purpose of ranking them by scores. * **[Leaderboard Reads](leaderboard-meters.md)**: Metered by API calls that read from Leaderboards. @@ -131,7 +131,7 @@ of ranking them by scores. ### Statistics -Azure Playfab Statistics is a cross-platform service that allows to track the activity of players within the game. +PlayFab Statistics is a cross-platform service that allows to track the activity of players within the game. * **[Statistics Reads](statistics-meters.md)**: Metered by API calls that read from Statistics. * **[Statistics Writes](statistics-meters.md)**: Metered by API calls that write to Statistics. diff --git a/playfab-docs/pricing/Meters/profile-reads.md b/playfab-docs/pricing/Meters/profile-reads.md index a0ddb336b..c1c804464 100644 --- a/playfab-docs/pricing/Meters/profile-reads.md +++ b/playfab-docs/pricing/Meters/profile-reads.md @@ -10,11 +10,11 @@ keywords: playfab, pricing ms.localizationpriority: medium --- -# Profile Reads +# Profile reads Profile includes any data stored related to the player profile, entity profile, character profile, groups, and inventory. Profile data is information that applies to an individual player, group of players, or items, and is stored as Key/Value Pairs (KVPs) by PlayFab. -The following APIs cause the Profile read meter to increment. +The following APIs increment the profile read meter. ## Admin APIs @@ -22,7 +22,7 @@ The following APIs cause the Profile read meter to increment. Checks the global count for the limited edition item. - [GetAllSegments](/rest/api/playfab/admin/play-stream/get-all-segments?view=playfab-rest&preserve-view=true) - Retrieves an array of player segment definitions. Results from this can be used in subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names can change the ID for that segment will not change. + Retrieves an array of player segment definitions. Results from this can be used in subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names can change the ID for that segment won't change. - [ExportMasterPlayerData](/rest/api/playfab/admin/account-management/export-master-player-data?view=playfab-rest&preserve-view=true) Exports all associated data of a master player account. @@ -31,16 +31,16 @@ The following APIs cause the Profile read meter to increment. Retrieves the specified version of the title's catalog of virtual goods, including all defined properties. - [GetContentList](/rest/api/playfab/admin/content/get-content-list?view=playfab-rest&preserve-view=true) - List all contents of the title and get statistics such as size. + Lists all contents of the title and gets statistics such as size. - [GetDataReport](/rest/api/playfab/admin/player-data-management/get-data-report?view=playfab-rest&preserve-view=true) Retrieves a download URL for the requested report. - [GetPlayerSegments](/rest/api/playfab/admin/play-stream/get-player-segments?view=playfab-rest&preserve-view=true) - List all segments that a player currently belongs to at this moment in time. + Lists all segments that a player currently belongs to at this moment in time. - [GetPlayerTags](/rest/api/playfab/admin/play-stream/get-player-tags?view=playfab-rest&preserve-view=true) - Get all tags with a given Namespace (optional) from a player profile. + Gets all tags with a given Namespace (optional) from a player profile. - [GetPolicy](/rest/api/playfab/admin/authentication/get-policy?view=playfab-rest&preserve-view=true) Gets the requested policy. @@ -55,7 +55,7 @@ The following APIs cause the Profile read meter to increment. Retrieves the set of items defined for the specified store, including all prices defined. - [GetTitleData](/rest/api/playfab/admin/title-wide-data-management/get-title-data?view=playfab-rest&preserve-view=true) - Retrieves the key-value store of custom title settings which can be read by the client. + Retrieves the key-value store of custom title settings that can be read by the client. - [GetUserAccountInfo](Retrieves the relevant details for a specified user, based upon a match against a supplied unique identifier) Retrieves the relevant details for a specified user, based upon a match against a supplied unique identifier. @@ -64,34 +64,34 @@ The following APIs cause the Profile read meter to increment. Gets all bans for a user. - [GetUserData](/rest/api/playfab/admin/player-data-management/get-user-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which is readable and writable by the client. + Retrieves the title-specific custom data for the user that's readable and writable by the client. - [GetUserInternalData](/rest/api/playfab/admin/player-data-management/get-user-internal-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which cannot be accessed by the client. + Retrieves the title-specific custom data for the user, which can't be accessed by the client. - [GetUserInventory](/rest/api/playfab/admin/player-item-management/get-user-inventory?view=playfab-rest&preserve-view=true) Retrieves the specified user's current inventory of virtual goods - [GetUserPublisherData](/rest/api/playfab/admin/player-data-management/get-user-publisher-data?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which is readable and writable by the client. + Retrieves the publisher-specific custom data for the user that's readable and writable by the client. - [GetUserPublisherInternalData](/rest/api/playfab/admin/player-data-management/get-user-publisher-internal-data?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which cannot be accessed by the client. + Retrieves the publisher-specific custom data for the user that can't be accessed by the client. - [GetUserPublisherReadOnlyData](/rest/api/playfab/admin/player-data-management/get-user-publisher-read-only-data?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which can only be read by the client. + Retrieves the publisher-specific custom data for the user that can only be read by the client. - [GetUserReadOnlyData](/rest/api/playfab/admin/player-data-management/get-user-read-only-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which can only be read by the client. + Retrieves the title-specific custom data for the user that can only be read by the client. - [ListVirtualCurrencyTypes](/rest/api/playfab/admin/title-wide-data-management/list-virtual-currency-types?view=playfab-rest&preserve-view=true) - Retuns the list of all defined virtual currencies for the title + Returns the list of all defined virtual currencies for the title - [GetPlayerIdFromAuthToken](/rest/api/playfab/admin/account-management/get-player-id-from-auth-token?view=playfab-rest&preserve-view=true) Gets a player's ID from an auth token. - [GetPlayersInSegment](/rest/api/playfab/admin/play-stream/get-players-in-segment?view=playfab-rest&preserve-view=true) - Allows for paging through all players in a given segment. This API creates a snapshot of all player profiles that match the segment definition at the time of its creation and lives through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation Token. Profiles that change during the course of paging will not be reflected in the results. AB Test segments are currently not supported by this operation. + Allows for paging through all players in a given segment. This API creates a snapshot of all player profiles that match the segment definition at the time of its creation and lives through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation Token. Profiles that change during paging won't be reflected in the results. AB Test segments are currently not supported by this operation. - [GetExperiments](/rest/api/playfab/experimentation/experimentation/get-experiments?view=playfab-rest&preserve-view=true) Gets the details of all experiments for a title. @@ -105,13 +105,13 @@ The following APIs cause the Profile read meter to increment. ## Client APIs - [GetAllUsersCharacters](/rest/api/playfab/client/characters/get-all-users-characters?view=playfab-rest&preserve-view=true) - Lists all of the characters that belong to a specific user. CharacterIds are not globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness. + Lists all of the characters that belong to a specific user. CharacterIds aren't globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness. - [GetCatalogItems](/rest/api/playfab/client/title-wide-data-management/get-catalog-items?view=playfab-rest&preserve-view=true) Retrieves the specified version of the title's catalog of virtual goods, including all defined properties. - [GetCharacterData](/rest/api/playfab/client/character-data/get-character-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the character which is readable and writable by the client. + Retrieves the title-specific custom data for the character that's readable and writable by the client. - [GetCharacterInventory](/rest/api/playfab/client/player-item-management/get-character-inventory?view=playfab-rest&preserve-view=true) Retrieves the specified character's current inventory of virtual goods. @@ -120,7 +120,7 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of ranked characters for the given statistic, starting from the indicated point in the leaderboard. - [GetCharacterReadOnlyData](/rest/api/playfab/client/character-data/get-character-read-only-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the character which can only be read by the client. + Retrieves the title-specific custom data for the character that can only be read by the client. - [GetCharacterStatistics](/rest/api/playfab/client/characters/get-character-statistics?view=playfab-rest&preserve-view=true) Retrieves the details of all title-specific statistics for the user. @@ -132,7 +132,7 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of ranked friends of the current player for the given statistic, centered on the requested PlayFab user. If PlayFabId is empty or null will return currently logged in user. - [GetFriendsList](/rest/api/playfab/client/friend-list-management/get-friends-list?view=playfab-rest&preserve-view=true) - Retrieves the current friend list for the local user, constrained to users who have PlayFab accounts. Friends from linked accounts (Facebook, Steam) are also included. You may optionally exclude some linked services' friends. + Retrieves the current friend list for the local user, constrained to users who have PlayFab accounts. Friends from linked accounts (Facebook, Steam) are also included. You can optionally exclude some linked services' friends. - [GetLeaderboard](/rest/api/playfab/client/player-data-management/get-leaderboard?view=playfab-rest&preserve-view=true) Retrieves a list of ranked users for the given statistic, starting from the indicated point in the leaderboard. @@ -147,13 +147,13 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of all of the user's characters for the given statistic. - [GetPaymentToken](/rest/api/playfab/client/player-item-management/get-payment-token?view=playfab-rest&preserve-view=true) - For payments flows where the provider requires playfab (the fulfiller) to initiate the transaction, but the client completes the rest of the flow. In the Xsolla case, the token returned here will be passed to Xsolla by the client to create a cart. Poll GetPurchase using the returned OrderId once you've completed the payment. + For payment flows where the provider requires PlayFab (the fulfiller) to initiate the transaction, but the client completes the rest of the flow. In the Xsolla case, the token returned here will be passed to Xsolla by the client to create a cart. Poll GetPurchase using the returned OrderId once you've completed the payment. - [GetPlayerProfile](/rest/api/playfab/client/account-management/get-player-profile?view=playfab-rest&preserve-view=true) Retrieves the player's profile. - [GetPlayerSegments](/rest/api/playfab/client/play-stream/get-player-segments?view=playfab-rest&preserve-view=true) - List all segments that a player currently belongs to at this moment in time. + Lists all segments that a player currently belongs to at this moment in time. - [GetPlayerStatistics](/rest/api/playfab/client/player-data-management/get-player-statistics?view=playfab-rest&preserve-view=true) Retrieves the indicated statistics (current version and values for all statistics, if none are specified), for the local player. @@ -162,10 +162,10 @@ The following APIs cause the Profile read meter to increment. Retrieves the information on the available versions of the specified statistic. - [GetPlayerTags](/rest/api/playfab/client/play-stream/get-player-tags?view=playfab-rest&preserve-view=true) - Get all tags with a given Namespace (optional) from a player profile. + Gets all tags with a given Namespace (optional) from a player profile. - [GetPlayerTrades](/rest/api/playfab/client/trading/get-player-trades?view=playfab-rest&preserve-view=true) - Gets all trades the player has either opened or accepted, optionally filtered by trade status. + Gets all trades the player either opens or accepts, optionally filtered by trade status. - [GetPlayFabIDsFromFacebookIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-facebook-ids?view=playfab-rest&preserve-view=true) Retrieves the unique PlayFab identifiers for the given set of Facebook identifiers. @@ -180,16 +180,16 @@ The following APIs cause the Profile read meter to increment. Retrieves the unique PlayFab identifiers for the given set of generic service identifiers. A generic identifier is the service name plus the service-specific ID for the player, as specified by the title when the generic identifier was added to the player account. - [GetPlayFabIDsFromGoogleIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-google-ids?view=playfab-rest&preserve-view=true) - Retrieves the unique PlayFab identifiers for the given set of Google identifiers. The Google identifiers are the IDs for the user accounts, available as "id" in the Google+ People API calls. + Retrieves the unique PlayFab identifiers for the given set of Google identifiers. The Google identifiers are the IDs for the user accounts, available as `id` in the Google+ People API calls. - [GetPlayFabIDsFromKongregateIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-kongregate-ids?view=playfab-rest&preserve-view=true) - Retrieves the unique PlayFab identifiers for the given set of Kongregate identifiers. The Kongregate identifiers are the IDs for the user accounts, available as "user_id" from the Kongregate API methods(ex: http://developers.kongregate.com/docs/client/getUserId). + Retrieves the unique PlayFab identifiers for the given set of Kongregate identifiers. The Kongregate identifiers are the IDs for the user accounts, available as `user_id` from the Kongregate API methods(for example, https://docs.kongregate.com/docs/concepts-handling-guests). - [GetPlayFabIDsFromNintendoSwitchDeviceIds](/rest/api/playfab/client/account-management/get-playfab-ids-from-nintendo-switch-device-ids?view=playfab-rest&preserve-view=true) Retrieves the unique PlayFab identifiers for the given set of Nintendo Switch identifiers. - [GetPlayFabIDsFromPSNAccountIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-psn-account-ids?view=playfab-rest&preserve-view=true) - Retrieves the unique PlayFab identifiers for the given set of PlayStation™Network identifiers. + Retrieves the unique PlayFab identifiers for the given set of PlayStation™ Network identifiers. - [GetPlayFabIDsFromSteamIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-steam-ids?view=playfab-rest&preserve-view=true) Retrieves the unique PlayFab identifiers for the given set of Steam identifiers. The Steam identifiers are the profile IDs for the user accounts, available as SteamId in the Steamworks Community API calls. @@ -207,7 +207,7 @@ The following APIs cause the Profile read meter to increment. Retrieves a purchase along with its current PlayFab status. Returns inventory items from the purchase that are still active. - [GetSharedGroupData](/rest/api/playfab/client/shared-group-data/get-shared-group-data?view=playfab-rest&preserve-view=true) - Retrieves data stored in a shared group object, as well as the list of members in the group. Non-members of the group may use this to retrieve group data, including membership, but they will not receive data for keys marked as private. Shared Groups are designed for sharing data between a very small number of players, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). + Retrieves data stored in a shared group object, and the list of members in the group. Non-members of the group use this to retrieve group data, including membership, but they won't receive data for keys marked as private. Shared Groups are designed for sharing data between a small number of players. For more information, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). - [GetStoreItems](/rest/api/playfab/client/title-wide-data-management/get-store-items?view=playfab-rest&preserve-view=true) Retrieves the set of items defined for the specified store, including all prices defined. @@ -219,51 +219,51 @@ The following APIs cause the Profile read meter to increment. Retrieves the user's PlayFab account details. - [LoginWithAndroidDeviceID](/rest/api/playfab/client/authentication/login-with-android-device-id?view=playfab-rest&preserve-view=true) - Signs the user in using the Android device identifier, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using the Android device identifier, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithCustomID](/rest/api/playfab/client/authentication/loginwithcustomid?view=playfab-rest&preserve-view=true) - Signs the user in using a custom unique identifier generated by the title, returning a session identifier that can subsequently be used for API calls which require an authenticated user + Signs the user in using a custom unique identifier generated by the title, returning a session identifier that can later be used for API calls that require an authenticated user - [LoginWithEmailAddress](/rest/api/playfab/client/authentication/login-with-email-address?view=playfab-rest&preserve-view=true) - Signs the user into the PlayFab account, returning a session identifier that can subsequently be used for API calls which require an authenticated user. Unlike most other login API calls, LoginWithEmailAddress does not permit the creation of new accounts via the CreateAccountFlag. Email addresses may be used to create accounts via RegisterPlayFabUser. + Signs the user into the PlayFab account, returning a session identifier that can later be used for API calls that require an authenticated user. Unlike most other login API calls, LoginWithEmailAddress doesn't permit the creation of new accounts via the CreateAccountFlag. Email addresses can be used to create accounts via RegisterPlayFabUser. - [LoginWithFacebook](/rest/api/playfab/client/authentication/login-with-facebook?view=playfab-rest&preserve-view=true) - Signs the user in using a Facebook access token, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using a Facebook access token, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithFacebookInstantGamesId](/rest/api/playfab/client/authentication/login-with-facebook-instant-games-id?view=playfab-rest&preserve-view=true) - Signs the user in using a Facebook Instant Games ID, returning a session identifier that can subsequently be used for API calls which require an authenticated user. Requires Facebook Instant Games to be configured. + Signs the user in using a Facebook Instant Games ID, returning a session identifier that can then be used for API calls that require an authenticated user. Requires Facebook Instant Games to be configured. - [LoginWithGameCenter](/rest/api/playfab/client/authentication/loginwithgamecenter?view=playfab-rest&preserve-view=true) - Signs the user in using an iOS Game Center player identifier, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an iOS Game Center player identifier, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithGoogleAccount](/rest/api/playfab/client/authentication/login-with-game-center?view=playfab-rest&preserve-view=true) - Signs the user in using an iOS Game Center player identifier, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an iOS Game Center player identifier, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithIOSDeviceID](/rest/api/playfab/client/authentication/login-with-google-account?view=playfab-rest&preserve-view=true) - Signs the user in using their Google account credentials. + Signs the user in by using their Google account credentials. - [LoginWithKongregate](/rest/api/playfab/client/authentication/login-with-kongregate?view=playfab-rest&preserve-view=true) - Signs the user in using a Kongregate player account. + Signs the user in by using a Kongregate player account. - [LoginWithNintendoSwitchDeviceId](/rest/api/playfab/client/authentication/login-with-nintendo-switch-device-id?view=playfab-rest&preserve-view=true) - Signs the user in using a Nintendo Switch Device ID, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using a Nintendo Switch Device ID, returning a session identifier that can then be used for API calls that require an authenticated user. - [LoginWithOpenIdConnect](/rest/api/playfab/client/authentication/login-with-openid-connect?view=playfab-rest&preserve-view=true) - Logs in a user with an Open ID Connect JWT created by an existing relationship between a title and an Open ID Connect provider. + Logs in a user by using an Open ID Connect JWT created by an existing relationship between a title and an Open ID Connect provider. - [LoginWithPlayFab](/rest/api/playfab/client/authentication/login-with-playfab?view=playfab-rest&preserve-view=true) - which require an authenticated user. Unlike most other login API calls, LoginWithPlayFab does not permit the creation of new accounts via the CreateAccountFlag. Username/Password credentials may be used to create accounts via RegisterPlayFabUser, or added to existing accounts using AddUsernamePassword. + which require an authenticated user. Unlike most other login API calls, `LoginWithPlayFab` doesn't permit the creation of new accounts via the `CreateAccountFlag`. Username/Password credentials can be used to create accounts via `RegisterPlayFabUser`, or added to existing accounts using `AddUsernamePassword`. -- [LoginWithPSN](/rest/api/playfab/client/authentication/login-with-psn?view=playfab-rest&preserve-view=true) Signs the user into the PlayFab account, returning a session identifier that can subsequently be used for API calls which require an authenticated user. Unlike most other login API calls, LoginWithPlayFab does not permit the creation of new accounts via the CreateAccountFlag. Username/Password credentials may be used to create accounts via RegisterPlayFabUser, or added to existing accounts using AddUsernamePassword. +- [LoginWithPSN](/rest/api/playfab/client/authentication/login-with-psn?view=playfab-rest&preserve-view=true) Signs the user into the PlayFab account, returning a session identifier that can then be used for API calls that require an authenticated user. Unlike most other login API calls, `LoginWithPlayFab` doesn't permit the creation of new accounts via the `CreateAccountFlag`. Username/Password credentials are used to create accounts via `RegisterPlayFabUser`, or added to existing accounts using `AddUsernamePassword`. - [LoginWithSteam](/rest/api/playfab/client/authentication/login-with-steam?view=playfab-rest&preserve-view=true) - Signs the user in using a Steam authentication ticket, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using a Steam authentication ticket, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithTwitch](/rest/api/playfab/client/authentication/login-with-twitch?view=playfab-rest&preserve-view=true) - Signs the user in using a Twitch access token. + Signs the user in by using a Twitch access token. - [LoginWithXbox](/rest/api/playfab/client/authentication/loginwithxbox?view=playfab-rest&preserve-view=true) - Signs the user in using a Xbox Live Token, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an Xbox Live Token, returning a session identifier that can later be used for API calls that require an authenticated user. - [GetPlayerCombinedInfo](/rest/api/playfab/client/account-management/get-player-combined-info?view=playfab-rest&preserve-view=true) Retrieves all of the user's different kinds of info. @@ -281,7 +281,7 @@ The following APIs cause the Profile read meter to increment. Gets information about a group and its roles. - [IsMember](/rest/api/playfab/groups/groups/is-member?view=playfab-rest&preserve-view=true) - Checks to see if an entity is a member of a group or role within the group. + Checks if an entity is a member of a group or role within the group. - [ListGroupApplications](/rest/api/playfab/groups/groups/list-group-applications?view=playfab-rest&preserve-view=true) Lists all outstanding requests to join a group. @@ -318,22 +318,22 @@ The following APIs cause the Profile read meter to increment. ## Server APIs - [EvaluateRandomResultTable](/rest/api/playfab/server/player-item-management/evaluate-random-result-table?view=playfab-rest&preserve-view=true) - Returns the result of an evaluation of a Random Result Table - the ItemId from the game Catalog which would have been added to the player inventory, if the Random Result Table were added via a Bundle or a call to UnlockContainer. + Returns the result of an evaluation of a Random Result Table - the `ItemId` from the game Catalog that would have been added to the player inventory, if the Random Result Table were added via a Bundle or a call to UnlockContainer. - [GetAllSegments](/rest/api/playfab/server/play-stream/get-all-segments?view=playfab-rest&preserve-view=true) - Retrieves an array of player segment definitions. Results from this can be used in subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names can change the ID for that segment will not change. + Retrieves an array of player segment definitions. Results from this can be used in subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names can change the ID for that segment won't change. - [GetAllUsersCharacters](/rest/api/playfab/server/characters/get-all-users-characters?view=playfab-rest&preserve-view=true) - Lists all of the characters that belong to a specific user. CharacterIds are not globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness. + Lists all of the characters that belong to a specific user. CharacterIds aren't globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness. - [GetCatalogItems](/rest/api/playfab/server/title-wide-data-management/get-catalog-items?view=playfab-rest&preserve-view=true) Retrieves the specified version of the title's catalog of virtual goods, including all defined properties. - [GetCharacterData](/rest/api/playfab/server/character-data/get-character-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which is readable and writable by the client. + Retrieves the title-specific custom data for the user that's readable and writable by the client. - [GetCharacterInternalData](/rest/api/playfab/server/character-data/get-character-internal-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user's character which cannot be accessed by the client. + Retrieves the title-specific custom data for the user's character that can't be accessed by the client. - [GetCharacterInventory](/rest/api/playfab/server/player-item-management/get-character-inventory?view=playfab-rest&preserve-view=true) Retrieves the specified character's current inventory of virtual goods. @@ -347,7 +347,7 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of ranked friends of the given player for the given statistic, starting from the indicated point in the leaderboard. - [GetFriendsList](/rest/api/playfab/server/friend-list-management/get-friends-list?view=playfab-rest&preserve-view=true) - Retrieves the current friends for the user with PlayFabId, constrained to users who have PlayFab accounts. Friends from linked accounts (Facebook, Steam) are also included. You may optionally exclude some linked services' friends. + Retrieves the current friends for the user with `PlayFabId`, constrained to users who have PlayFab accounts. Friends from linked accounts (Facebook, Steam) are also included. You might optionally exclude some linked services' friends. - [GetLeaderboard](/rest/api/playfab/server/player-data-management/get-leaderboard?view=playfab-rest&preserve-view=true) Retrieves a list of ranked users for the given statistic, starting from the indicated point in the leaderboard. @@ -362,16 +362,16 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of all of the user's characters for the given statistic. - [GetPlayerCombinedInfo](/rest/api/playfab/server/player-data-management/get-player-combined-info?view=playfab-rest&preserve-view=true) - Returns whatever info is requested in the response for the user. Note that PII (like email address, facebook id) may be returned. All parameters default to false. + Returns whatever info is requested in the response for the user. Note that personal date, like email address, facebook ID, might be returned. All parameters default to false. - [GetPlayerProfile](/rest/api/playfab/server/account-management/get-player-profile?view=playfab-rest&preserve-view=true) Retrieves the player's profile. - [GetPlayerSegments](/rest/api/playfab/server/play-stream/get-player-segments?view=playfab-rest&preserve-view=true) - List all segments that a player currently belongs to at this moment in time. + Lists all segments that a player currently belongs to at this moment in time. - [GetPlayersInSegment](/rest/api/playfab/server/play-stream/get-players-in-segment?view=playfab-rest&preserve-view=true) - Allows for paging through all players in a given segment. This API creates a snapshot of all player profiles that match the segment definition at the time of its creation and lives through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation Token. Profiles that change during the course of paging will not be reflected in the results. AB Test segments are currently not supported by this operation. + Allows for paging through all players in a given segment. This API creates a snapshot of all player profiles that match the segment definition at the time of its creation and lives through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation Token. Profiles that change during paging aren't reflected in the results. AB Test segments are currently not supported by this operation. - [GetPlayerStatistics](/rest/api/playfab/server/player-data-management/get-player-statistics?view=playfab-rest&preserve-view=true) Retrieves the current version and values for the indicated statistics, for the local player. @@ -380,7 +380,7 @@ The following APIs cause the Profile read meter to increment. Retrieves the information on the available versions of the specified statistic. - [GetPlayerTags](/rest/api/playfab/server/play-stream/get-player-tags?view=playfab-rest&preserve-view=true) - Get all tags with a given Namespace (optional) from a player profile. + Gets all tags with a given Namespace (optional) from a player profile. - [GetPlayFabIDsFromFacebookIDs](/rest/api/playfab/server/account-management/getplayfabidsfromfacebookids?view=playfab-rest&preserve-view=true) Retrieves the unique PlayFab identifiers for the given set of Facebook identifiers. @@ -413,7 +413,7 @@ The following APIs cause the Profile read meter to increment. Retrieves the associated PlayFab account identifiers for the given set of server custom identifiers. - [GetSharedGroupData](/rest/api/playfab/server/shared-group-data/get-shared-group-data?view=playfab-rest&preserve-view=true) - Retrieves data stored in a shared group object, as well as the list of members in the group. The server can access all public and private group data. Shared Groups are designed for sharing data between a very small number of players, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). + Retrieves data stored in a shared group object, and the list of members in the group. The server can access all public and private group data. Shared Groups are designed for sharing data between a small number of players. For more information, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). - [GetStoreItems](/rest/api/playfab/server/title-wide-data-management/get-store-items?view=playfab-rest&preserve-view=true) Retrieves the set of items defined for the specified store, including all prices defined, for the specified player. @@ -431,30 +431,30 @@ The following APIs cause the Profile read meter to increment. Gets all bans for a user. - [GetUserData](/rest/api/playfab/server/player-data-management/get-user-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which is readable and writable by the client. + Retrieves the title-specific custom data for the user that is readable and writable by the client. - [GetUserInternalData](/rest/api/playfab/server/player-data-management/get-user-internal-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which cannot be accessed by the client. + Retrieves the title-specific custom data for the user that can't be accessed by the client. - [GetUserInventory](/rest/api/playfab/server/player-item-management/get-user-inventory?view=playfab-rest&preserve-view=true) Retrieves the specified user's current inventory of virtual goods. - [GetUserPublisherData](/rest/api/playfab/server/player-data-management/get-user-publisher-data?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which is readable and writable by the client. + Retrieves the publisher-specific custom data for the user that is readable and writable by the client. - [GetUserPublisherInternalData](/rest/api/playfab/server/player-data-management/getuserpublisherinternaldata?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which cannot be accessed by the client. + Retrieves the publisher-specific custom data for the user that can't be accessed by the client. - [GetUserPublisherReadOnlyData](/rest/api/playfab/server/player-data-management/get-user-publisher-internal-data?view=playfab-rest&preserve-view=true) - [GetUserReadOnlyData](/rest/api/playfab/server/player-data-management/update-user-read-only-data?view=playfab-rest&preserve-view=true) - Updates the title-specific custom data for the user which can only be read by the client. + Updates the title-specific custom data for the user that can only be read by the client. - [LoginWithServerCustomId](/rest/api/playfab/server/authentication/login-with-server-custom-id?view=playfab-rest&preserve-view=true) - Securely login a game client from an external server backend using a custom identifier for that player. Server Custom ID and Client Custom ID are mutually exclusive and cannot be used to retrieve the same player account. + Securely login a game client from an external server backend using a custom identifier for that player. Server Custom ID and Client Custom ID are mutually exclusive and can't be used to retrieve the same player account. - [LoginWithXbox](/rest/api/playfab/server/authentication/login-with-xbox?view=playfab-rest&preserve-view=true) - Signs the user in using a Xbox Live Token from an external server backend, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an Xbox Live Token from an external server backend, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithXboxId](/rest/api/playfab/server/authentication/login-with-xbox-id?view=playfab-rest&preserve-view=true) - Signs the user in using an Xbox ID and Sandbox ID, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an Xbox ID and Sandbox ID, returning a session identifier that can later be used for API calls that require an authenticated user. diff --git a/playfab-docs/pricing/Meters/profile-writes.md b/playfab-docs/pricing/Meters/profile-writes.md index aa0fae355..0ffc81b93 100644 --- a/playfab-docs/pricing/Meters/profile-writes.md +++ b/playfab-docs/pricing/Meters/profile-writes.md @@ -175,7 +175,7 @@ The following APIs cause the Profile writes meter to increment. Adds users to the set of those able to update both the shared data, as well as the set of users in the group. Only users in the group (and the server) can add new members. Shared Groups are designed for sharing data between a very small number of players, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). - [AddUsernamePassword](/rest/api/playfab/client/account-management/addusernamepassword?) - Adds playfab username/password auth to an existing account created via an anonymous auth method, e.g. automatic device ID login. + Adds PlayFab username/password auth to an existing account created via an anonymous auth method, e.g. automatic device ID login. - [AndroidDevicePushNotificationRegistration](/rest/api/playfab/client/platform-specific-methods/androiddevicepushnotificationregistration?) Registers the Android device to receive push notifications @@ -247,7 +247,7 @@ The following APIs cause the Profile writes meter to increment. Registers the iOS device to receive push notifications - [RegisterPlayFabUser](/rest/api/playfab/client/authentication/registerplayfabuser?) - Registers a new Playfab user account, returning a session identifier that can subsequently be used for API calls which require an authenticated user. You must supply either a username or an email address. + Registers a new PlayFab user account, returning a session identifier that can subsequently be used for API calls which require an authenticated user. You must supply either a username or an email address. - [RemoveContactEmail](/rest/api/playfab/client/account-management/removecontactemail?) Removes a contact email from the player's profile. diff --git a/playfab-docs/sdks/c-sharp/index.md b/playfab-docs/sdks/c-sharp/index.md index 12319eeaf..1734e8737 100644 --- a/playfab-docs/sdks/c-sharp/index.md +++ b/playfab-docs/sdks/c-sharp/index.md @@ -39,7 +39,7 @@ The C# PlayFab SDK shouldn't be used if there's a more specific SDK that is suit Specific PlayFab SDK is available for: * [Unity PlayFab SDK GitHub repo](https://github.com/PlayFab/UnitySDK) -For a full list of the different PlayFab SDKs, see [Azure PlayFab SDK](../playfab-sdk-intro.md). +For a full list of the different PlayFab SDKs, see [PlayFab SDK](../playfab-sdk-intro.md). ## Using the SDK diff --git a/playfab-docs/sdks/c/index.md b/playfab-docs/sdks/c/index.md index 7611116bb..23f4a01fd 100644 --- a/playfab-docs/sdks/c/index.md +++ b/playfab-docs/sdks/c/index.md @@ -48,8 +48,8 @@ Here are some notable differences when compared to other, more general purpose, ## Benefits of this SDK -- Allows titles to control the memory allocations when calling Playfab Services. See [Managing Memory Allocations](memory.md) to learn more. -- Allows titles to gain full control of thread handling when calling Playfab Services. See [Making async calls in the PlayFab Services SDK](async.md) to learn more. +- Allows titles to control the memory allocations when calling PlayFab Services. See [Managing Memory Allocations](memory.md) to learn more. +- Allows titles to gain full control of thread handling when calling PlayFab Services. See [Making async calls in the PlayFab Services SDK](async.md) to learn more. - Portable C interface that allows maximum compatibility across platforms, compilers, and languages. - High-performance telemetry pipeline with support for low-cost queuing and batch transmission of events. diff --git a/playfab-docs/sdks/playfab-sdk-intro.md b/playfab-docs/sdks/playfab-sdk-intro.md index ececa5ede..7a4fb679f 100644 --- a/playfab-docs/sdks/playfab-sdk-intro.md +++ b/playfab-docs/sdks/playfab-sdk-intro.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab SDKs +title: PlayFab SDKs author: joannaleecy -description: Azure PlayFab SDKs +description: PlayFab SDKs ms.author: jenelleb ms.date: 03/04/2024 ms.topic: article @@ -27,7 +27,7 @@ For broad API categories in these SDKs, see [API REST operation groups](/rest/ap | Language | Platform/environments | |-----------------------------------|-------------------------------------------| -| C/C++ | [Windows (Win32), iOS, MacOS, Android, Linux](c/index.md), [GDK (Xbox and Windows)](c/index.md), [Switch](https://dev.azure.com/PlayFabPrivate/Switch/_git/PlayFabCSdk.Switch), [PlayStation 4](https://dev.azure.com/PlayFabPrivate/PS4/_git/PlayFabCSdk.PS4), [PlayStation 5](https://dev.azure.com/PlayFabPrivate/PS5/_git/PlayFabCSdk.PS5) | +| C/C++ | [Windows (Win32), iOS, macOS, Android, Linux](c/index.md), [GDK (Xbox and Windows)](c/index.md), [Switch](https://dev.azure.com/PlayFabPrivate/Switch/_git/PlayFabCSdk.Switch), [PlayStation 4](https://dev.azure.com/PlayFabPrivate/PS4/_git/PlayFabCSdk.PS4), [PlayStation 5](https://dev.azure.com/PlayFabPrivate/PS5/_git/PlayFabCSdk.PS5) | | Legacy C++ | [Windows (Win32), iOS, Android, Linux](playfab-cpp/index.md), [Switch](https://dev.azure.com/PlayFabPrivate/Switch/_git/XPlatCppSdk-Private-Switch), [PlayStation 4](https://dev.azure.com/PlayFabPrivate/PS4/_git/XPlatCppSdk-Private-Ps4), [PlayStation 5](https://dev.azure.com/PlayFabPrivate/PS5/_git/XPlatCppSdk-Private-PS5) | | C# | [C#/.NET environments](c-sharp/index.md) besides Unity | | Java | [Android apps](java/index.md) | From 4cfac5c220a5422d7327d476dfa35af644353201 Mon Sep 17 00:00:00 2001 From: anaisnlawson Date: Wed, 25 Feb 2026 18:32:35 -0500 Subject: [PATCH 62/76] Update instructions for disabling multiple events (#2839) Co-authored-by: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> --- playfab-docs/data-analytics/ingest-data/opt-in-events.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/playfab-docs/data-analytics/ingest-data/opt-in-events.md b/playfab-docs/data-analytics/ingest-data/opt-in-events.md index b7d56f995..f24221e1c 100644 --- a/playfab-docs/data-analytics/ingest-data/opt-in-events.md +++ b/playfab-docs/data-analytics/ingest-data/opt-in-events.md @@ -78,9 +78,9 @@ To preview event data, select the graph icon next to any event. A data explorer To disable multiple events at once: 1. Select **Bulk Edit Events** in the header. -1. Choose **Set all PlayStream events to none** or **Set all telemetry events to none** (or both). -1. Select **Apply** to make the changes. -1. Review the toast notification and the unsaved changes indicator, then **Save** or **Discard Changes** as needed. +1. Choose **Turn off emission for all PlayStream events** or **Turn off emission for all telemetry events** (or both). +1. Select **Bulk edit** to make the changes. +1. **Save** or **Discard Changes** as needed. ## Save configuration changes From a2c6cec9b1475c50264cac1f4669c4f1e58df8c3 Mon Sep 17 00:00:00 2001 From: Berni Mora <93845766+BerniME@users.noreply.github.com> Date: Thu, 26 Feb 2026 12:33:25 -0600 Subject: [PATCH 63/76] PFMultiplayer SDK v1.8.7 Release Notes (#2840) * Release notes PFM 1.8.7 * PR feedback --------- Co-authored-by: Berni Mora Escobar --- .../lobby-and-matchmaking-release-notes.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md index ec64b7acd..d2301018a 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md @@ -12,6 +12,14 @@ ms.localizationpriority: medium # PlayFab Multiplayer C++ SDK release notes +## 1.8.7 + +February 26, 2026 + +### Bug fixes + +- Fixed an issue where the library may crash after losing a WebSocket connection while paused in a debugger. + ## 1.8.6 February 13, 2026 From 73d5483ca0b50e81baac2fe1c18db85d29e824d1 Mon Sep 17 00:00:00 2001 From: Ernesto Cortes Groman Date: Thu, 26 Feb 2026 12:56:49 -0800 Subject: [PATCH 64/76] =?UTF-8?q?=E2=9C=A8=20MicrosoftStore=20redeem=20doc?= =?UTF-8?q?s=20(#2828)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ernesto Cortes Groman Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --- .../marketplace-integrations/microsoft.md | 177 ++++++++++++++++++ .../marketplace-integrations/overview.md | 9 +- .../marketplace-integrations/toc.yml | 2 + .../marketplace-redemption/microsoft.md | 156 +++++++++++++++ .../marketplace-redemption/overview.md | 14 +- .../marketplace-redemption/toc.yml | 2 + 6 files changed, 353 insertions(+), 7 deletions(-) create mode 100644 playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/microsoft.md create mode 100644 playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/microsoft.md diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/microsoft.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/microsoft.md new file mode 100644 index 000000000..7bcb51d98 --- /dev/null +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/microsoft.md @@ -0,0 +1,177 @@ +--- +title: Marketplace integration - Microsoft Store +author: ernestoc +description: How to redeem Microsoft Store in-app purchases through PlayFab Economy v2 +ms.author: ernestoc +ms.date: 02/23/2026 +ms.topic: tutorial +ms.service: azure-playfab +keywords: playfab, integration, marketplace, microsoft store, xbox, redeem, consumable, durable +ms.localizationpriority: medium +--- + +# Marketplace integration: Microsoft Store + +This tutorial shows you how to redeem Microsoft Store in-app purchases (including Xbox) through PlayFab Economy v2 using the [RedeemMicrosoftStoreInventoryItems](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) API. + +By the end of this tutorial, you: + +- Created an add-on in Partner Center +- Configured the required Partner Center and PlayFab settings +- Linked your Microsoft Store product to a PlayFab catalog Bundle +- Called the Redeem API and verified items in your player's inventory + +## Prerequisites + +1. A [Partner Center](https://partner.microsoft.com/) account with access to your app. +2. An app already created in Partner Center. +3. A Title already created in [Game Manager](https://developer.playfab.com/). +4. The player calling the Redeem API must be authenticated to PlayFab using an Xbox Live identity (for example, via `LoginWithXbox`). Players authenticated with other identity types (such as CustomID or email) do not have the Xbox context required for this flow. + +## Supported product types + +The `RedeemMicrosoftStoreInventoryItems` API supports the following Microsoft Store product types: + +- **Developer-managed consumable** — Products that can be purchased, used, and purchased again (for example, in-game currency packs). The game service is responsible for tracking fulfillment. +- **Durable** — Products that are purchased once and owned permanently (for example, DLC, expansion packs, season passes, or cosmetic items). + +> [!IMPORTANT] +> **Store-managed consumables are not supported.** PlayFab Economy v2 cannot redeem Store-managed consumables. If your add-on is configured as a Store-managed consumable, the Redeem API returns an HTTP 200 response with empty results and no error, making the issue difficult to diagnose. + +## Step 1: Create your add-on in Partner Center + +1. Sign in to [Partner Center](https://partner.microsoft.com/) and navigate to your app. +2. Under **Add-ons**, select **Create a new add-on**. +3. Select the appropriate product type: + - **Developer-managed consumable** for items that can be repurchased (currency, consumable packs). + - **Durable** for one-time purchases (DLC, season passes, cosmetic unlocks). +4. Complete the add-on configuration (pricing, descriptions, and so on) and submit it. + +> [!IMPORTANT] +> When creating a Developer-managed consumable, Partner Center displays a warning that reads: *"Xbox requires consumables to be managed, so do not use this option and create a 'managed consumable' add-on instead. If you have any questions, contact your Microsoft representative."** +> +> This warning reflects general Xbox platform guidance and **does not apply to the PlayFab redemption flow**. Developer-managed consumables work correctly on Xbox when used with PlayFab's `RedeemMicrosoftStoreInventoryItems` API. You can safely proceed with this product type. + +5. After creating your add-on, note the **Store ID**—the alphanumeric string (for example, `9NBLGGH42CFD`) shown in Partner Center. Use this value for PlayFab, **not** the developer-defined Product ID, or the add-on name. + +For more information on product types, see [Choosing the right product type](/gaming/gdk/docs/store/commerce/getting-started/xstore-choosing-the-right-product-type). + +## Step 2: Configure Product Group, Dev Studio, and Business Partner ID + +This step configures the delegated Xbox Security Token Service (XSTS) token flow that PlayFab uses to query the Microsoft Store Collections API on behalf of the player. + +> [!WARNING] +> The Product Group, Dev Studio, and Business Partner ID configuration is the most commonly missed step. Without it, the Redeem API call succeeds (HTTP 200) but the Collections API returns zero items—resulting in empty `Succeeded`, `Failed`, and `TransactionIds` arrays with no error message. + +1. In [Partner Center](https://partner.microsoft.com/), navigate to **Developer Settings** > **Xbox Live** > **Web Services** and generate a Business Partner Certificate if you have not already. +2. Navigate to **Developer Settings** > **Xbox Live** > **Business Partner** and note the **Business Partner ID** that matches the web service your relying party is tied to. +3. Create a **Dev Studio** (or use an existing one) and set its **Dev Studio ID** to match the **Business Partner ID** from step 2. If the Dev Studio already has a different ID, create a new Dev Studio rather than changing the existing value. Changing it can break existing services. +4. Create a **Product Group** and assign it to the Dev Studio from step 3. +5. Add your game product **and** all of your add-ons to the **Included in this product group** list. Items must be explicitly moved from the "available" side to the "included" side. +6. Select **Save**. +7. Navigate to your game's **Xbox Settings** page and confirm the linked **Business Partner** matches the one from step 2. +8. **Republish** your game product and all add-ons to the Microsoft Store in your target sandbox or RETAIL environment. + +For the full configuration walkthrough, see [Configure products with delegated authentication (XSTS tokens)](/gaming/gdk/docs/store/commerce/service-to-service/xstore-authenticating-your-service#additional-configuration-required-to-view-and-manage-products-with-delegated-authentication-xsts-tokens). + +## Step 3: Enable the Xbox Network add-on in Game Manager + +The Xbox Network add-on links your Partner Center product to your PlayFab title and enables Xbox token validation for Microsoft Store redemption. + +1. Open [Game Manager](https://developer.playfab.com/) and select your **Title**. +2. Select **Add-ons** from the left navigation menu. +3. Locate and select the **Xbox Network** add-on (labeled **Distribute for Xbox**). +4. Select the correct **Seller ID** from the dropdown. If you do not see the correct Seller ID, select **Sign in with a different partner center account**. +5. Select your **Partner Center Product ID** from the dropdown and confirm the **Xbox Live Title ID** (decimal) matches what you see in Partner Center under **Xbox services** > **Xbox Settings**. +6. Select **Install Xbox Network** to save the configuration. + +For more details, see [Xbox Live add-on configuration](/gaming/playfab/identity/player-identity/platform-specific-authentication/xbox-live-add-on). + +> [!NOTE] +> Game Manager also has a separate **Microsoft Store** add-on page (also under **Add-ons**). While it does not require configuration, it contains useful guidance including confirmation of supported product types and details on the Dev Studio ID and Business Partner ID setup. + +## Step 4: Create a PlayFab Bundle with Marketplace Mapping + +To link your Microsoft Store product to your PlayFab catalog, create a **Bundle** with a **Marketplace Mapping** (AlternateId). + +1. In [Game Manager](https://developer.playfab.com/), navigate to **Economy** > **Catalog (V2)** > **Bundles**. +2. Select **New bundle** (or edit an existing one). +3. Under the **Marketplace Mapping** section, add a new mapping: + - Set the **Marketplace type** to `MicrosoftStore` (case-sensitive, must be exactly `MicrosoftStore`). + - Set the **value** to the exact **Store ID** from Partner Center (for example, `9NBLGGH42CFD`). Do not use the developer-defined Product ID or the add-on name. +4. Add the items you want the player to receive when this Bundle is redeemed (for example, in-game currency, virtual items). +5. **Publish** the Bundle. Unpublished (draft) Bundles are not matched during redemption. + +For more information on alternate IDs, see [Alternate IDs](/gaming/playfab/economy-monetization/economy-v2/catalog/content-types-tags-and-properties#alternate-ids). + +## Step 5: Acquire and provide the Xbox token + +When calling the [RedeemMicrosoftStoreInventoryItems](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) API, you must provide a valid Xbox token in the `XboxToken` parameter. + + +- If you are using the **GDK C API**, use: + + ```cpp + XUserGetTokenAndSignatureAsync // with method "POST", URL "https://playfabapi.com/", and empty body "" + ``` + +All three parameters (method, URL, and body) must be provided exactly as shown. An incorrectly obtained token causes the Collections API query to fail silently, returning empty results with no error. + +## Step 6: Test the integration + +Before considering your integration complete, verify the full end-to-end flow: + +1. Ensure your add-on is published to the sandbox or environment you are testing in. +2. Sign in as a test player using an Xbox Live identity and make a test purchase of the add-on through the Microsoft Store. The player must have an unredeemed purchase on their account before the Redeem API has anything to detect. +3. Call `RedeemMicrosoftStoreInventoryItems` with the player's `XboxToken`. +4. Verify the response contains entries in the `Succeeded` array and that the corresponding items appear in the player's PlayFab inventory. + +> [!NOTE] +> **Developer-managed consumable fulfillment:** After a Developer-managed consumable is redeemed, PlayFab automatically reports it as **fulfilled** (consumed) with the Microsoft Store on your behalf. The fulfillment step is necessary before the player can purchase the consumable again. If the consumable does not appear as fulfilled after a successful redemption, retry the `RedeemMicrosoftStoreInventoryItems` call. If the issue persists, escalate to the PlayFab team through your support channel. For details, see [Managing consumables and refunds](/gaming/gdk/docs/store/commerce/service-to-service/xstore-managing-consumables-and-refunds). + +## Troubleshooting + +If the `RedeemMicrosoftStoreInventoryItems` call returns successfully (HTTP 200) but the `Succeeded`, `Failed`, and `TransactionIds` arrays in the response are all empty, the Microsoft Store Collections API is not finding any matching items to redeem. A configuration issue typically causes this behavior. Check the following items: + +| Issue | Resolution | +|---|---| +| **Wrong product type** | Ensure the add-on is a **Developer-managed consumable** or **Durable**, not a Store-managed consumable. PlayFab does not support Store-managed consumables. | +| **Incorrect Store ID in PlayFab** | Confirm the Marketplace Mapping value matches the **Store ID** (alphanumeric string like `9NBLGGH42CFD`), not the developer-defined Product ID or add-on name. | +| **Bundle not published** | Publish the Bundle in your PlayFab catalog. Draft Bundles are not matched during redemption. | +| **Missing Product Group configuration** | Confirm your game and add-ons are included in a Product Group tied to the correct Dev Studio and Business Partner ID. The Product Group configuration is the most commonly missed step. See [Step 2](#step-2-configure-product-group-dev-studio-and-business-partner-id). | +| **Xbox Network add-on not configured** | Install and configure the Xbox Network add-on in Game Manager. See [Step 3](#step-3-enable-the-xbox-network-add-on-in-game-manager). | +| **No unredeemed purchase** | The player must have an unredeemed purchase of the product before the API can detect and redeem it. Make a test purchase first. | +| **Consumable not fulfilled** | PlayFab automatically fulfills Developer-managed consumables after redemption. If a consumable was redeemed once but does not redeem again, retry the `RedeemMicrosoftStoreInventoryItems` call. If the issue persists, escalate to the PlayFab team through your support channel. See [Managing consumables and refunds](/gaming/gdk/docs/store/commerce/service-to-service/xstore-managing-consumables-and-refunds). | +| **Sandbox mismatch** | Ensure the add-on is published to the same sandbox you are testing in. The Xbox token carries sandbox context, so both must match. | +| **Invalid Xbox token** | Verify the token is obtained with the correct parameters: method `POST`, URL `https://playfabapi.com/`, and an empty body string `""`. | +| **Player not authenticated with Xbox identity** | The player must be signed in to PlayFab using an Xbox Live identity (for example, via `LoginWithXbox`). Other identity types do not have the Xbox context required for redemption. | + +If the API returns an HTTP error (such as 400), check the error response for the following codes: + +| Error code | Description | +|---|---| +| `InvalidCatalogItemConfiguration` | The Bundle or Marketplace Mapping is misconfigured in the PlayFab catalog. | +| `InvalidXboxLiveToken` | The Xbox token is invalid, expired, or obtained with incorrect parameters. | +| `AccountNotLinked` | The player's PlayFab account is not linked to an Xbox Live identity. | +| `XboxInaccessible` | PlayFab cannot reach Xbox services. The error may be transient. | +| `XboxXASSExchangeFailure` | The XSTS token exchange failed. Verify your Business Partner and relying party configuration. | + +> [!TIP] +> If the call succeeds (HTTP 200) but returns empty results and all other configuration looks correct, check the Product Group configuration first. The Product Group step is the most commonly missed step. + +## Note on PC / Windows titles + +This tutorial covers the Xbox flow, which uses delegated XSTS tokens (passed via the `XboxToken` parameter). For **PC / Windows titles**, Microsoft recommends using User Store IDs with Microsoft Entra ID for service-to-service authentication instead. For more information, see [Requesting a User Store ID for service-to-service authentication](/gaming/gdk/docs/store/commerce/service-to-service/xstore-requesting-a-userstoreid) and [Authenticating your service — User Store IDs](/gaming/gdk/docs/store/commerce/service-to-service/xstore-authenticating-your-service#authenticating-through-microsoft-entra-id-and-user-store-ids). + +## See also + +- [RedeemMicrosoftStoreInventoryItems API reference](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) +- [Fraud prevention quickstart](/gaming/playfab/economy-monetization/economy-v2/fraud-prevention/quickstart) +- [Xbox Live add-on configuration](/gaming/playfab/identity/player-identity/platform-specific-authentication/xbox-live-add-on) +- [Authenticating your service (XSTS tokens)](/gaming/gdk/docs/store/commerce/service-to-service/xstore-authenticating-your-service) +- [Choosing the right product type](/gaming/gdk/docs/store/commerce/getting-started/xstore-choosing-the-right-product-type) +- [Consumable-based ecosystems](/gaming/gdk/docs/store/commerce/fundamentals/xstore-consumable-based-ecosystems) +- [Managing consumables and refunds](/gaming/gdk/docs/store/commerce/service-to-service/xstore-managing-consumables-and-refunds) +- [Alternate IDs (Marketplace Mapping)](/gaming/playfab/economy-monetization/economy-v2/catalog/content-types-tags-and-properties#alternate-ids) +- [How to successfully integrate an Apple app into Game Manager](apple.md) +- [How to successfully integrate a Google app into Game Manager](google.md) diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/overview.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/overview.md index ace6dec1c..5aea5df3c 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/overview.md +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/overview.md @@ -17,12 +17,12 @@ Marketplace integration with PlayFab allows you to connect your game to various ## Supported Marketplaces ### Steam -Integrate your game with Steam to leverage its extensive user base and robust infrastructure for in-game purchases. Configure the necessary settings in the Game Manager to connect your PlayFab title with Steam. +Integrate your game with Steam to use its extensive user base and robust infrastructure for in-game purchases. To connect your PlayFab title with Steam, configure the necessary settings in Game Manager. See our [Steam integration documentation](steam.md). ### Apple -Connect your game to the Apple App Store to enable in-app purchases for iOS users. Follow the integration steps in the Game Manager to ensure a smooth connection between PlayFab and Apple's marketplace. +To enable in-app purchases for iOS users, connect your game to the Apple App Store. To ensure a smooth connection between PlayFab and Apple's marketplace, follow the integration steps in Game Manager. See our [Apple App Store integration documentation](apple.md). @@ -31,4 +31,9 @@ Integrate with Google Play to offer in-app purchases for Android users. Set up t See our [Google Play Store integration documentation](google.md). +### Microsoft Store +To enable in-app purchases for Xbox and Windows users, integrate with the Microsoft Store. To link your PlayFab title with the Microsoft Store marketplace, configure the Xbox Network add-on in Game Manager and set up your Product Group in Partner Center. + +See our [Microsoft Store integration documentation](microsoft.md). + By integrating with these marketplaces, you can streamline the purchase process for your players and manage all transactions through PlayFab's unified platform. \ No newline at end of file diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/toc.yml b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/toc.yml index 917f0196f..55603507d 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/toc.yml +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/toc.yml @@ -5,5 +5,7 @@ items: href: google.md - name: Apple App Store href: apple.md + - name: Microsoft Store + href: microsoft.md - name: Steam href: steam.md \ No newline at end of file diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/microsoft.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/microsoft.md new file mode 100644 index 000000000..51fc5d121 --- /dev/null +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/microsoft.md @@ -0,0 +1,156 @@ +--- +title: Redemption with the Microsoft Store Marketplace +author: ernestoc +description: Set up PlayFab and the Microsoft Store to enable purchases and redemption on Xbox and Windows +ms.author: fprotti +ms.date: 02/22/2026 +ms.topic: tutorial +ms.service: azure-playfab +keywords: playfab, integration, marketplace, microsoft store, xbox, purchase, redemption +ms.localizationpriority: medium +--- + +# Set up PlayFab and the Microsoft Store to enable purchases + +This tutorial shows you how to: + +- Create a purchasable product in the Microsoft Store +- Map it to a PlayFab bundle +- Redeem purchased items into a player's inventory using the [RedeemMicrosoftStoreInventoryItems](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) API + +## Prerequisites + +1. A Title in PlayFab's [Game Manager](https://developer.playfab.com/). +2. An existing [integration between the selected Title and the Microsoft Store](../marketplace-integrations/microsoft.md), including: + - The **Xbox Network** add-on installed and configured in Game Manager. + - The **Product Group**, **Dev Studio**, and **Business Partner ID** configured in Partner Center. +3. A [Partner Center](https://partner.microsoft.com/) account with access to your app. +4. An app already created in Partner Center. +5. The player calling the Redeem API must be authenticated to PlayFab using an Xbox Live identity (for example, via `LoginWithXbox`). Players authenticated with other identity types (such as CustomID or email) do not have the Xbox context required for this flow. + +## Step 1: Create your add-on in Partner Center + +If you did not create an add-on in Partner Center as part of the [marketplace integration setup](../marketplace-integrations/microsoft.md#step-1-create-your-add-on-in-partner-center), follow these steps: + +1. Sign in to [Partner Center](https://partner.microsoft.com/) and navigate to your app. +2. Under **Add-ons**, select **Create a new add-on**. +3. Select the appropriate product type: + - **Developer-managed consumable** for items that can be repurchased (currency, consumable packs). + - **Durable** for one-time purchases (DLC, season passes, cosmetic unlocks). +4. Complete the add-on configuration (pricing, descriptions, and so on) and submit it. +5. After creating your add-on, note the **Store ID**—the alphanumeric string (for example, `9NBLGGH42CFD`) shown in Partner Center. Use this value for the marketplace mapping in PlayFab, **not** the developer-defined Product ID, or the add-on name. + +> [!IMPORTANT] +> **Store-managed consumables are not supported.** Only Developer-managed consumables and Durables work with the `RedeemMicrosoftStoreInventoryItems` API. Partner Center may display a warning suggesting that Developer-managed consumables are not supported on Xbox. This warning does not apply when using the PlayFab redemption flow. For more information, see [Choosing the right product type](/gaming/gdk/docs/store/commerce/getting-started/xstore-choosing-the-right-product-type). + +6. Publish the add-on to the sandbox or environment you intend to test in. + +## Step 2: Create a Bundle in Game Manager + +> [!NOTE] +> Before creating a bundle in **Game Manager**, create and publish the items you want to add to the bundle in your Catalog. If you need guidance on how to create an item, refer to [this step](../../tutorials/craftingGame/crafting-game-game-manager.md#step-4---create-your-first-item). + +To enable a marketplace mapping between **Game Manager** and the **Microsoft Store**, you need to create a **Bundle** in Game Manager. A bundle can contain multiple items with different quantities, and PlayFab adds them to the player's inventory once redeemed. Follow these steps: + +1. Go to [Game Manager](https://developer.playfab.com/) and navigate to your **Title**. +2. From the left navigation menu, choose **Engage** > **Economy**. +3. Select the **Bundles** tab. +4. Select **New bundle**. +5. Add any information you want to the **Bundle**, such as items and prices. +6. Scroll down to the end of the page and select **Save and publish** if you want it to be redeemable by players right away. Select **Save as draft** if you want to publish it at a later date. + +### Add items to your Bundle + +A bundle by itself does not grant any items to a player. You must first link items to it. Once redeemed, the bundle grants those items to the specific player. + +To add items to your bundle: + +1. Go to the **Items** section in edit mode. +2. Select **Add**. A window appears showing all your catalog items. +3. Find your desired item and select **Add** next to it. +4. Select the **Add** button at the bottom. + +## Step 3: Enable marketplace mapping + +To ensure that when a player purchases a product from the Microsoft Store it gets properly matched and assigned in Game Manager, you must configure the **Marketplace Mapping** on your Bundle. + +1. Navigate to your bundle in edit mode. +2. Scroll down to the **Marketplace Mapping** section. +3. From the **Marketplace** dropdown, select **MicrosoftStore** (case-sensitive, must be exactly `MicrosoftStore`). +4. For your **Marketplace ID**, use the exact **Store ID** from Partner Center (for example, `9NBLGGH42CFD`). Do **not** use the developer-defined Product ID. +5. Select the **+** at the right side of that row and **Save** your changes. + +> [!IMPORTANT] +> The Bundle must be **published** (not left as a draft) for it to be matched during redemption. The redemption API does not detect unpublished catalog items. + +For more information on alternate IDs, see [Alternate IDs](/gaming/playfab/economy-monetization/economy-v2/catalog/content-types-tags-and-properties#alternate-ids). + +## Step 4: Authenticate your player + +Before making a redemption call, you must ensure that the player is properly authenticated. For Xbox and Microsoft Store scenarios, use [LoginWithXbox](/rest/api/playfab/client/authentication/login-with-xbox) to authenticate the player with PlayFab. + +After a successful call to `LoginWithXbox`, PlayFab returns an `EntityToken` that you must use in the headers of your redemption call with the `X-EntityToken` key. + +## Step 5: Acquire the Xbox token + +The `RedeemMicrosoftStoreInventoryItems` API requires a valid Xbox token in the `XboxToken` parameter. This token is separate from the `EntityToken` used for authentication. + +- If you are using the **GDK C API**, use: + + ```cpp + XUserGetTokenAndSignatureAsync // with method "POST", URL "https://playfabapi.com/", and empty body "" + ``` + +All three parameters (method, URL, and body) must be provided exactly as shown. An incorrectly obtained token causes the Microsoft Store Collections API query to fail silently, returning no items. + +## Step 6: Make a purchase + +The player must purchase the add-on from the Microsoft Store before you can redeem it through PlayFab. This purchase can be made through the Xbox or Windows Store interface. + +> [!NOTE] +> If you are testing in a sandbox environment, ensure the player account and the add-on are both published to the same sandbox. The player must have an **unredeemed purchase** on their account for the redemption API to find items to redeem. + +## Step 7: Redeem the purchase + +With your player authenticated, the Xbox token acquired, and a purchase completed, you are ready to call the [RedeemMicrosoftStoreInventoryItems](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) API. + +Include the `EntityToken` as the `X-EntityToken` header, and provide the Xbox token in the request body: + +```json +{ + "XboxToken": "{Your Xbox token from GetTokenAndSignatureAsync}" +} +``` + +### How redemption works + +When the `RedeemMicrosoftStoreInventoryItems` call is made, PlayFab uses the Xbox token to query the Microsoft Store Collections API for any unredeemed purchases associated with the player's account. It then matches those purchases against the **Store IDs** configured in your PlayFab Bundle Marketplace Mappings and grants the corresponding items. + +A successful response includes a `200` status code alongside the [RedeemMicrosoftStoreInventoryItemsResponse](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items), which contains: + +- **Succeeded**—A list of successfully redeemed items. +- **Failed**—A list of items that failed to redeem. +- **TransactionIds**—IDs for each redemption transaction. + +Each redemption action triggers a corresponding event in the player's transaction history, which can be retrieved from the **Transaction History (V2)** tab under the player's overview page in [Game Manager](https://developer.playfab.com/). + +Alongside the record in the player's transaction history, an `items_redeemed` **PlayStream** event is also triggered and logged. You can access these logs for your Title by going to the **Data** page under the **Analyze** section of the left navigation bar in [Game Manager](https://developer.playfab.com/). + +### Fulfillment for Developer-managed consumables + +If the redeemed product is a **Developer-managed consumable**, PlayFab automatically reports it as **fulfilled** (consumed) with the Microsoft Store on your behalf after a successful redemption. The fulfillment step is necessary before the player can repurchase the same consumable. If the consumable does not appear as fulfilled after a successful redemption, retry the `RedeemMicrosoftStoreInventoryItems` call. If the issue persists, escalate to the PlayFab team through your support channel. Durables do not require fulfillment because they are one-time purchases. For more information, see [Managing consumables and refunds](/gaming/gdk/docs/store/commerce/service-to-service/xstore-managing-consumables-and-refunds). + +## Troubleshooting + +If the redemption call returns `200` but all three arrays (`Succeeded`, `Failed`, `TransactionIds`) are empty, the Microsoft Store Collections API is not finding any matching items. This result typically indicates a configuration issue. See the [troubleshooting section](../marketplace-integrations/microsoft.md#troubleshooting) in the Microsoft Store integration guide for a full list of common causes and resolutions. + +If the API returns an HTTP error (such as 400), check the error response for codes like `InvalidCatalogItemConfiguration`, `InvalidXboxLiveToken`, or `AccountNotLinked`. + +## See also + +- [Microsoft Store marketplace integration](../marketplace-integrations/microsoft.md) +- [RedeemMicrosoftStoreInventoryItems API reference](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) +- [Fraud prevention quickstart](/gaming/playfab/economy-monetization/economy-v2/fraud-prevention/quickstart) +- [Xbox Live add-on configuration](/gaming/playfab/identity/player-identity/platform-specific-authentication/xbox-live-add-on) +- [How to successfully integrate an Apple app into Game Manager](../marketplace-integrations/apple.md) +- [How to successfully integrate a Google app into Game Manager](../marketplace-integrations/google.md) diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/overview.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/overview.md index a6a050ca9..f7742ed2f 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/overview.md +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/overview.md @@ -18,25 +18,29 @@ After a successful marketplace integration, the next step is to focus on redeemi ### Apple -Redemption from the Apple marketplace involves verifying the purchase receipt with Apple's servers and updating the player's inventory or account accordingly. For more details see [Apple redemption documentation](apple.md) +Redemption from the Apple marketplace involves verifying the purchase receipt with Apple's servers and updating the player's inventory or account accordingly. For more information, see [Apple redemption documentation](apple.md). ### Google -Redemption from the Google marketplace involves verifying the purchase receipt with Google's servers and updating the player's inventory or account accordingly. For more details see [Google redemption documentation](google.md) +Redemption from the Google marketplace involves verifying the purchase receipt with Google's servers and updating the player's inventory or account accordingly. For more information, see [Google redemption documentation](google.md). + +### Microsoft Store + +Redemption from the Microsoft Store involves using an Xbox token to query the Microsoft Store Collections API for unredeemed purchases and granting the corresponding items to the player's inventory. For more information, see [Microsoft Store redemption documentation](microsoft.md). ### Steam -Redemption from the Steam marketplace involves verifying the purchase receipt with Steam's servers and updating the player's inventory accordingly. For more details see [Steam redemption documentation](steam.md) +Redemption from the Steam marketplace involves verifying the purchase receipt with Steam's servers and updating the player's inventory accordingly. For more information, see [Steam redemption documentation](steam.md). ## Subscription Redemption ### Apple Subscriptions -Subscription redemption from the Apple marketplace involves verifying the subscription receipt with Apple's servers and updating the player's account accordingly. For more details see [Apple subscription documentation](ios-subscription-redemption.md). +Subscription redemption from the Apple marketplace involves verifying the subscription receipt with Apple's servers and updating the player's account accordingly. For more information, see [Apple subscription documentation](ios-subscription-redemption.md). ### Google Subscriptions -Subscription redemption from the Google marketplace involves verifying the subscription receipt with Google's servers and updating the player's account accordingly. For more details see [Google subscription documentation](google-subscription-redemption.md). +Subscription redemption from the Google marketplace involves verifying the subscription receipt with Google's servers and updating the player's account accordingly. For more information, see [Google subscription documentation](google-subscription-redemption.md). ## Conclusion diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/toc.yml b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/toc.yml index 94c081921..615836729 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/toc.yml +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/toc.yml @@ -3,6 +3,8 @@ items: href: overview.md - name: Google redemption href: google.md + - name: Microsoft Store redemption + href: microsoft.md - name: Steam redemption href: steam.md - name: Google subscription redemption From 83121f58169c214a87bc57a92f678d593ad5b035 Mon Sep 17 00:00:00 2001 From: eduardobadilla07 Date: Fri, 27 Feb 2026 09:26:45 -0800 Subject: [PATCH 65/76] Add v1.10.17 release notes (#2834) --- .../multiplayer/networking/release-notes.md | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/playfab-docs/multiplayer/networking/release-notes.md b/playfab-docs/multiplayer/networking/release-notes.md index 04e85e45b..68de2998d 100644 --- a/playfab-docs/multiplayer/networking/release-notes.md +++ b/playfab-docs/multiplayer/networking/release-notes.md @@ -13,11 +13,20 @@ ms.localizationpriority: medium # PlayFab Party Release Notes > [!NOTE] -> Support for the Xbox Development Kit (XDK) and Windows 7 platforms ended on August 1, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using Windows 7 or XDK versions of the PlayFab Party library. +> Support for the XDK and Windows 7 platforms ended on August 1, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services continue to operate with no impact to any titles currently using Windows 7 or XDK versions of the PlayFab Party library. > [!NOTE] > Support for 32-bit Android platforms (arm7 and x86) ended on October 19, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using the PlayFab Party library on 32-bit Android platforms. +## 1.10.17 + +February 23, 2026 + +- Android: Fix Bluetooth microphones not working. +- Linux: Remove SafeStack. +- Apple: Hide OpenSSL symbols from Party. +- Nintendo Switch 2: Resolved TCP connection error when IP changes. + ## 1.10.16 February 2, 2026 @@ -33,14 +42,14 @@ February 2, 2026 December 17, 2025 -- Nintendo Switch 2: Added 10 second timeout for web requests. +- Nintendo Switch 2: Added 10-second timeout for web requests. ## 1.10.14 December 9, 2025 - Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has expired. -- Android: Added support for 16 KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). +- Android: Added support for 16-KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). ## 1.10.13 @@ -48,14 +57,14 @@ December 9, 2025 October 14, 2025 - Fixed an issue that caused the microphone to not function properly on iOS 26. -- Apple: Added support for Arm64 .xcframework on iOS. +- Apple: Added support for Arm64.xcframework on iOS. ## 1.10.12 October 6, 2025 - Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has expired. -- Android: Added support for 16 KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). +- Android: Added support for 16-KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). - Apple: Added support for Arm64 simulator builds on iOS. ### Bug fixes @@ -102,7 +111,7 @@ November 12, 2024 October 14, 2024 -- Added support for up to 128 devices per network. For more details, see [Scalable networks](party-features.md#scalable-networks-up-to-128-devices-per-network). +- Added support for up to 128 devices per network. For more information, see [Scalable networks](party-features.md#scalable-networks-up-to-128-devices-per-network). - Increased `c_maxNetworkConfigurationMaxDeviceCount` from 32 to 128. - Updated internal diagnostics. - Updated build settings for security hardening. @@ -226,7 +235,7 @@ June 28, 2023 ### Bug fixes -- Fixed a bug where [`PartyLocalChatControl::SetAudioRenderVolume`](reference/classes/PartyLocalChatControl/methods/partylocalchatcontrol_setaudiorendervolume.md) didn't work properly for Nintendo Switch, PlayStation®4, and PlayStation®5. +- Fixed a bug where [`PartyLocalChatControl::SetAudioRenderVolume`](reference/classes/PartyLocalChatControl/methods/partylocalchatcontrol_setaudiorendervolume.md) wouldn't properly work for Nintendo Switch, PlayStation®4 and, PlayStation®5. “PlayStation” is a registered trademark or trademark of Sony Interactive Entertainment Inc. @@ -265,7 +274,7 @@ March 30, 2023 ### Bug fixes - Fixed a bug where Party could crash if it wasn't cleaned up before the host process started exiting. -- Changed behavior for peer-to-peer connection to fallback to a relayed connection if the link is disconnected unexpectedly. The previous behavior disconnected both devices from the network. +- Changed behavior for peer-to-peer connection to fall back to a relayed connection if the link is disconnected unexpectedly. The previous behavior would disconnect both the devices from the network. ## 1.7.20 @@ -273,7 +282,7 @@ February 8, 2023 ### Bug fixes -- Fixed a bug where audio from 44.1-kHz microphones might sound distorted. +- Fixed a bug where audio from 44.1-kHz microphones may sound distorted. - Improved diagnostic error messages for network errors reported by [PartyManager::GetErrorMessage()](reference/classes/PartyManager/methods/partymanager_geterrormessage.md). ## 1.7.19 From d3df627753e87f003dcb8f35aab2fb03d6873663 Mon Sep 17 00:00:00 2001 From: edigonzales-microsoft Date: Wed, 4 Mar 2026 12:07:38 -0800 Subject: [PATCH 66/76] Update uhfHeaderId in docfx.json for upcoming all up Gaming L2 Nav Header (#2844) Update uhfHeaderId in docfx.json for upcoming all up Gaming L2 Nav Header Note: Playfab headers are embedded / accessible within the new header so no information previously on Playfab header is lost. Reminder to self / doc team, this change is not to be merged until it is confirmed that the Nav update is also live from the MS Learn team. --- playfab-docs/docfx.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playfab-docs/docfx.json b/playfab-docs/docfx.json index 34969a045..1e6b3daeb 100644 --- a/playfab-docs/docfx.json +++ b/playfab-docs/docfx.json @@ -33,7 +33,7 @@ "overwrite": [], "externalReference": [], "globalMetadata": { - "uhfHeaderId": "MSDocsHeader-PlayFab", + "uhfHeaderId": "MSDocsHeader-Gaming", "breadcrumb_path": "/gaming/playfab/breadcrumb/toc.json", "feedback_system": "Standard", "feedback_product_url": "https://community.playfab.com/index.html", From b6eb9bd783c6824c19a2c9e90435ded71085f356 Mon Sep 17 00:00:00 2001 From: Andy McCalib Date: Thu, 5 Mar 2026 19:30:10 -0800 Subject: [PATCH 67/76] Add UI callbacks doc, clarify XAsyncBlock behavior during sync failures (#2845) - Add new ui-callbacks.md covering all five callback types, state machine model, response APIs, and platform override behavior - Update offline.md to clarify XAsyncBlock deferral during retry loops - Trim quickstart.md Step 4 to cross-reference ui-callbacks.md - Add UI Callbacks entry to toc.yml Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../player-progression/game-saves/offline.md | 21 ++- .../game-saves/quickstart.md | 45 ++--- .../player-progression/game-saves/toc.yml | 2 + .../game-saves/ui-callbacks.md | 175 ++++++++++++++++++ 4 files changed, 201 insertions(+), 42 deletions(-) create mode 100644 playfab-docs/player-progression/game-saves/ui-callbacks.md diff --git a/playfab-docs/player-progression/game-saves/offline.md b/playfab-docs/player-progression/game-saves/offline.md index c40c7417c..65a66f187 100644 --- a/playfab-docs/player-progression/game-saves/offline.md +++ b/playfab-docs/player-progression/game-saves/offline.md @@ -28,7 +28,7 @@ When network is unavailable or the user chooses to play offline, the system ente ### Handling Network Failures During Initial Sync -When `PFGameSaveFilesAddUserWithUiAsync()` is called without network connectivity, it triggers a `PFGameSaveFilesUiSyncFailedCallback`. Users can respond with two options: +When `PFGameSaveFilesAddUserWithUiAsync()` is called without network connectivity, it triggers a `PFGameSaveFilesUiSyncFailedCallback`. The `XAsyncBlock` callback doesn't fire while the system waits for the user's response—the async operation is paused until the user selects a terminal action. ```cpp // Handle sync failure callback @@ -48,8 +48,9 @@ void MyPFGameSaveFilesUiSyncFailedCallback(PFLocalUserHandle localUserHandle, PF ``` **User Response Options:** -- **Try Again**: Attempts the network call again (loops back to failure callback if still offline) -- **Use Offline**: `PFGameSaveFilesAddUserWithUiAsync` async callback reports `S_OK` but puts system into offline mode (can be detected with `PFGameSaveFilesIsConnectedToCloud()`) +- **Try Again (`Retry`)**: Retries the network call. If the retry also fails, this callback fires again and the user must respond again. The `XAsyncBlock` callback remains deferred through each retry loop. +- **Use Offline (`UseOffline`)**: The `XAsyncBlock` callback fires with `S_OK`, but the system enters offline mode (detectable with `PFGameSaveFilesIsConnectedToCloud()`). +- **Cancel**: The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. ### API Behavior in Offline Mode @@ -89,8 +90,12 @@ Use this API before attempting cloud operations to provide appropriate user feed ### Upload Behavior in Connected Mode -Even in connected mode, uploads can fail due to network issues. When this happens: -- Failure UI callback is triggered -- User can choose to retry or cancel -- If cancelled, async completion returns `E_PF_GAMESAVE_USER_CANCELLED` -- The game can call upload again later when network is restored +Even in connected mode, uploads can fail due to network issues or rate limits. When this happens, the `XAsyncBlock` callback doesn't fire immediately—the async operation pauses while the system waits for the user's response through the [UI callback state machine](./ui-callbacks.md#how-the-state-machine-works): + +1. The `PFGameSaveFilesUiSyncFailedCallback` fires with the error details. +2. The `XAsyncBlock` callback doesn't fire yet—the operation is paused while the system waits for a response. +3. If the user selects `Retry`, the upload retries. If it fails again, the callback fires again and the user must respond again. +4. If the user selects `Cancel`, the `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. +5. If a retry succeeds, the `XAsyncBlock` callback fires with `S_OK`. + +The game can call `PFGameSaveFilesUploadWithUiAsync()` again later when network is restored. diff --git a/playfab-docs/player-progression/game-saves/quickstart.md b/playfab-docs/player-progression/game-saves/quickstart.md index 187b07c92..48a8cb97e 100644 --- a/playfab-docs/player-progression/game-saves/quickstart.md +++ b/playfab-docs/player-progression/game-saves/quickstart.md @@ -298,47 +298,24 @@ If you aren't using the progress callback, wait for the `XAsyncBlock` to complet ## Step 4: Handle UI Callbacks (Optional) -Game Saves provides built-in UI for Xbox and Windows platforms, but you can customize the user experience by implementing your own UI callbacks. +Game Saves provides built-in UI for Xbox and Windows platforms. On other platforms (such as Steam Deck), your game must provide its own UI by handling callbacks. -### Platform Requirements -- **Xbox/Windows**: Built-in UI is provided; custom callbacks are optional -- **Other platforms** (Steam Deck, etc.): Custom UI callbacks are **required** - -### Types of UI Callbacks -- **Progress**: Show upload/download progress to users -- **Conflicts**: Handle situations where local and cloud saves differ -- **Active Device Contention**: Warn when user tries to sync on multiple devices -- **Sync Failures**: Handle network or other sync errors -- **Out of Storage**: Notify users when local storage is too full to sync - -### When Callbacks Trigger -UI callbacks only occur during two operations: -- `PFGameSaveFilesAddUserWithUiAsync` (download from cloud) -- `PFGameSaveFilesUploadWithUiAsync` (upload to cloud) - -### Implementation +UI callbacks fire during `PFGameSaveFilesAddUserWithUiAsync` and `PFGameSaveFilesUploadWithUiAsync`. Each callback pauses the async operation until your game responds—the `XAsyncBlock` callback doesn't fire until all UI callbacks are resolved. ```cpp // Set up custom UI callbacks (call this before AddUser or Upload operations) // See sample for detailed examples of these callbacks. -hr = PFGameSaveFilesSetUiCallbacks( - MyPFGameSaveFilesUiProgressCallback, nullptr, - MyPFGameSaveFilesUiSyncFailedCallback, nullptr, - MyPFGameSaveFilesUiActiveDeviceContentionCallback, nullptr, - MyPFGameSaveFilesUiConflictCallback, nullptr, - MyPFGameSaveFilesUiOutOfStorageCallback, nullptr); +PFGameSaveUICallbacks callbacks{}; +callbacks.progressCallback = MyProgressCallback; +callbacks.syncFailedCallback = MySyncFailedCallback; +callbacks.activeDeviceContentionCallback = MyActiveDeviceContentionCallback; +callbacks.conflictCallback = MyConflictCallback; +callbacks.outOfStorageCallback = MyOutOfStorageCallback; + +HRESULT hr = PFGameSaveFilesSetUiCallbacks(&callbacks); ``` -### Response APIs -Each callback has a corresponding response API: -- `PFGameSaveFilesSetUiProgressResponse()` - Respond to progress callback, letting users cancel -- `PFGameSaveFilesSetUiConflictResponse()` - Respond to conflict callbacks -- `PFGameSaveFilesSetUiActiveDeviceContentionResponse()` - Respond to device contention -- `PFGameSaveFilesSetUiSyncFailedResponse()` - Respond to sync failures -- `PFGameSaveFilesSetUiOutOfStorageResponse()` - Respond to local storage full issues - -> [!IMPORTANT] -> The Game Saves system waits for your response before continuing. Always call the appropriate response API when handling callbacks (except progress callbacks which don't need a response). +For the full list of callback types, response APIs, user actions, and details on how the state machine works, see [Game Saves UI callbacks](./ui-callbacks.md). ## Understanding Save Conflicts diff --git a/playfab-docs/player-progression/game-saves/toc.yml b/playfab-docs/player-progression/game-saves/toc.yml index 5b9f621b4..77d316fe7 100644 --- a/playfab-docs/player-progression/game-saves/toc.yml +++ b/playfab-docs/player-progression/game-saves/toc.yml @@ -12,6 +12,8 @@ items: href: steam-deck-implementation.md - name: Conflicts href: conflicts.md +- name: UI Callbacks + href: ui-callbacks.md - name: Offline Mode href: offline.md - name: Active Device Changes diff --git a/playfab-docs/player-progression/game-saves/ui-callbacks.md b/playfab-docs/player-progression/game-saves/ui-callbacks.md new file mode 100644 index 000000000..0579cba8a --- /dev/null +++ b/playfab-docs/player-progression/game-saves/ui-callbacks.md @@ -0,0 +1,175 @@ +--- +title: Game Saves UI callbacks +author: amccalib +description: How Game Saves UI callbacks work, including the state machine model, callback types, and response APIs. +ms.author: andmcc +ms.date: 03/06/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, game saves, ui callbacks, sync failed, conflict, progress +ms.localizationpriority: medium +--- + +# Game Saves UI callbacks + +Game Saves provides a set of UI callbacks that let your game respond to events during sync operations. On Xbox and Windows, the platform provides built-in UI for these events. On other platforms (such as Steam Deck), your game must implement its own UI by handling these callbacks. + +Setting callbacks on Xbox and Windows overrides the platform-provided UI with your implementation. This is useful if your game needs a consistent player experience across all platforms—register the same callbacks everywhere and the built-in UI won't appear. + +## How the state machine works + +Game Saves uses an internal state machine to coordinate UI callbacks with the async operation lifecycle. When a UI callback fires, the async operation pauses—the `XAsyncBlock` callback doesn't fire until the callback is resolved. The state machine doesn't progress until the game calls the corresponding response API or the async operation is canceled. + +This means: + +- Each callback type has a corresponding response API. Call the response API to tell the system what to do next. +- Response APIs can be called inside or outside the callback function. +- If a response action is `Retry`, the operation retries and may trigger the same callback again. +- The `XAsyncBlock` callback only fires once the operation reaches a terminal state—success, cancellation, or an offline fallback. + +For example, if an upload fails due to rate limits: + +1. `PFGameSaveFilesUiSyncFailedCallback` fires with the error. +2. The `XAsyncBlock` callback doesn't fire yet—the state machine waits for a response. +3. If the user selects `Retry` and the retry also fails, the sync failed callback fires again. +4. If the user selects `Cancel`, the `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. +5. If a retry succeeds, the `XAsyncBlock` callback fires with `S_OK`. + +## When callbacks trigger + +UI callbacks only fire during two async operations: + +| Operation | Callbacks that can trigger | +|-----------|--------------------------| +| `PFGameSaveFilesAddUserWithUiAsync` | Progress, Sync Failed, Active Device Contention, Conflict, Out of Storage | +| `PFGameSaveFilesUploadWithUiAsync` | Progress, Sync Failed | + +## Registering callbacks + +Register all callbacks before calling `PFGameSaveFilesAddUserWithUiAsync` or `PFGameSaveFilesUploadWithUiAsync`: + +```cpp +PFGameSaveUICallbacks callbacks{}; +callbacks.progressCallback = MyProgressCallback; +callbacks.progressContext = nullptr; +callbacks.syncFailedCallback = MySyncFailedCallback; +callbacks.syncFailedContext = nullptr; +callbacks.activeDeviceContentionCallback = MyActiveDeviceContentionCallback; +callbacks.activeDeviceContentionContext = nullptr; +callbacks.conflictCallback = MyConflictCallback; +callbacks.conflictContext = nullptr; +callbacks.outOfStorageCallback = MyOutOfStorageCallback; +callbacks.outOfStorageContext = nullptr; + +HRESULT hr = PFGameSaveFilesSetUiCallbacks(&callbacks); +``` + +## Callback reference + +### Progress + +Reports upload or download progress. Use `PFGameSaveFilesUiProgressGetProgress` inside the callback to retrieve the current `PFGameSaveFilesSyncState`, bytes completed, and bytes total. + +**Callback**: `PFGameSaveFilesUiProgressCallback` + +**Response API**: `PFGameSaveFilesSetUiProgressResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | + +> [!NOTE] +> The progress callback doesn't require a response to continue—the operation keeps progressing on its own. Only call the response API if the user wants to cancel. + +#### Sync states + +The `PFGameSaveFilesSyncState` enum indicates which phase the operation is in: + +| State | Description | Safe to write to save folder? | +|-------|-------------|-------------------------------| +| `NotStarted` | Operation hasn't begun | Yes | +| `PreparingForDownload` | Preparing to download from cloud | Yes | +| `Downloading` | Downloading from cloud | No | +| `PreparingForUpload` | Reading and compressing local files | No | +| `Uploading` | Upload to cloud in progress (local files captured) | Yes | +| `SyncComplete` | Operation finished | Yes | + +### Sync failed + +Fires when a sync operation fails, for example due to network issues or rate limits. + +**Callback**: `PFGameSaveFilesUiSyncFailedCallback` + +**Parameters**: Receives `PFGameSaveFilesSyncState` (the phase that failed) and `HRESULT` (the error code). + +**Response API**: `PFGameSaveFilesSetUiSyncFailedResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | +| `Retry` | Retries the failed operation. If the retry fails, this callback fires again. | +| `UseOffline` | Only valid during `PFGameSaveFilesAddUserWithUiAsync`. The `XAsyncBlock` callback fires with `S_OK`, but the system enters offline mode. Use `PFGameSaveFilesIsConnectedToCloud()` to detect this state. | + +For more details on offline mode behavior, see [Game Saves offline mode](./offline.md). + +### Active device contention + +Fires during `PFGameSaveFilesAddUserWithUiAsync` when another device is already the active device for this user. The callback receives `PFGameSaveDescriptor` structs for both the local and remote save data, which include device names, timestamps, and save sizes that you can display to help the user decide. + +**Callback**: `PFGameSaveFilesUiActiveDeviceContentionCallback` + +**Response API**: `PFGameSaveFilesSetUiActiveDeviceContentionResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | +| `Retry` | Retries—useful if the user expects the other device to release soon. If the other device is still active, this callback fires again. | +| `SyncLastSavedData` | Makes the local device active and syncs. The remote device can no longer upload and receives an active device changed notification. | + +For more details on active device behavior, see [Game Saves active device changes](./activedevicechanges.md). + +### Conflict + +Fires during `PFGameSaveFilesAddUserWithUiAsync` when local and cloud save data have diverged. The callback receives `PFGameSaveDescriptor` structs for both the local and remote save data. + +**Callback**: `PFGameSaveFilesUiConflictCallback` + +**Response API**: `PFGameSaveFilesSetUiConflictResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | +| `TakeLocal` | Keeps local save data and uploads it to the cloud. | +| `TakeRemote` | Discards local changes and downloads the cloud save data. | + +> [!IMPORTANT] +> Conflict resolution applies to the entire save, not individual files or folders. For details on how conflicts are detected at the atomic unit level and resolved globally, see [Game Saves conflicts](./conflicts.md). + +### Out of storage + +Fires during `PFGameSaveFilesAddUserWithUiAsync` when the local device doesn't have enough disk space to download save data from the cloud. The callback receives `requiredBytes` indicating how much space is needed. + +**Callback**: `PFGameSaveFilesUiOutOfStorageCallback` + +**Response API**: `PFGameSaveFilesSetUiOutOfStorageResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | +| `Retry` | Retries after the user frees local storage space. If there still isn't enough space, this callback fires again. | + +## Platform requirements + +| Platform | UI callbacks | +|----------|-------------| +| **Xbox and Windows** | Optional. Set callbacks to override the built-in UI. | +| **Other platforms** (Steam Deck, etc.) | **Required**. No built-in UI is available; your game must handle all callbacks. | + +For Steam Deck implementation details, see [Steam Deck implementation guide](./steam-deck-implementation.md). + +## Related content + +- [Game Saves quickstart](./quickstart.md) +- [Game Saves offline mode](./offline.md) +- [Game Saves conflicts](./conflicts.md) +- [Game Saves active device changes](./activedevicechanges.md) From 1b0ebbce919dc076082bf1185a2e5490b1eada89 Mon Sep 17 00:00:00 2001 From: Steven Rojas Lizano Date: Tue, 10 Mar 2026 10:11:18 -0600 Subject: [PATCH 68/76] Add missing releases notes from jan 2025 to mar 2026 (#2849) --- playfab-docs/release-notes/2025.md | 226 ++++++++++++++++++++++++++++ playfab-docs/release-notes/index.md | 42 ++++-- playfab-docs/release-notes/toc.yml | 4 +- playfab-docs/whats-new/toc.yml | 4 +- 4 files changed, 265 insertions(+), 11 deletions(-) create mode 100644 playfab-docs/release-notes/2025.md diff --git a/playfab-docs/release-notes/2025.md b/playfab-docs/release-notes/2025.md new file mode 100644 index 000000000..5f34b3bfc --- /dev/null +++ b/playfab-docs/release-notes/2025.md @@ -0,0 +1,226 @@ +--- +title: PlayFab Services SDK Release Notes 2025 +author: stevenLizano29 +description: PlayFab Services SDK Release Notes for 2025. +ms.author: v-stevenroj +ms.date: 03/09/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, development, release, apis, features +ms.localizationpriority: medium +--- +# PlayFab Services SDK Release Notes 2025 + +> [!NOTE] +> For release notes about service releases and product updates, see the [release notes](https://github.com/PlayFab/PlayFab/releases) section on [PlayFab's public GitHub repository](https://github.com/PlayFab/PlayFab) + +## 251219 + +Date: December 19, 2025 + + - Added StartDate field to Economy API + - Added error codes for new service errors + +## 251205 + +Date: December 5, 2025 + + - Added GetPlayFabIDsFromOpenIdSubjectIdentifiers to the Client and Server APIs + - Added the following calls to the Server API: + - LinkTwitchAccount + - LoginWithTwitch + - UnlinkTwitchAccount + - Added error codes for new service errors + +## 251121 + +Date: November 21, 2025 + + - Added MarketplaceConfigurationName to the Economy API + - Updated RestrictInvitesToLobbyOwner in the Multiplayer API + - Added error codes for new service errors + +## 251107 + +Date: November 7, 2025 + + - Added PageSize and SkipToken pagination fields to multiple calls in the Progression API + - Added JwsReceiptData type to the Economy API + - Added error codes for new service errors + +## 251024 + +Date: October 24, 2025 + + - Added AlternateIdType and AlternateIdValue fields to the Economy API + - Added error codes for new service errors + +## 251010 + +Date: October 10, 2025 + + - Added error codes for new service errors + +## 250926 + +Date: September 26, 2025 + + - Added RedeemAppleAppStoreWithJwsInventoryItems to the Economy API for Apple App Store JWS receipt validation + - Added error codes for new service errors + +## 250912 + +Date: September 12, 2025 + + - Added UnlinkAggregationSourceFromStatistic to the Progression API + - Added LinkXboxId to the Server API + - Added time range query types for store metrics in the Admin API + - Added error codes for new service errors + +## 250815 + +Date: August 15, 2025 + + - Added LeaderboardVersionEndConfig, LeaderboardEventEmissionConfig, and StatisticsEventEmissionConfig types to the Progression API + - Added pricing override types to the Economy API + - Added Apple and Xbox add-on configuration fields to the Addon API + - Added error codes for new service errors + +## 250801 + +Date: August 1, 2025 + + - Added GetStoreMetrics to the Admin API + - Added error codes for new service errors + +## 250718 + +Date: July 18, 2025 + + - Added CustomTags to GetTransactionHistory in the Economy API + - Added FunctionResultSize field to the CloudScript API + - Added error codes for new service errors + +## 250704 + +Date: July 4, 2025 + + - Added ContinuationToken and Count fields to the Economy API + - Added error codes for new service errors + +## 250620 + +Date: June 20, 2025 + + - Added VersionedCatalogsSource field to the Economy API + - Added error codes for new service errors + +## 250606 + +Date: June 6, 2025 + + - Added clawback tracking fields to transaction history in the Economy API (TransactionClawbackDetails) + - Added StatisticNames filter to GetEntityStatistics in the Progression API + - Added error codes for new service errors + +## 250526 + +Date: May 26, 2025 + + - Added the following calls to the Addon API for ToxMod management: + - CreateOrUpdateToxMod + - DeleteToxMod + - GetToxMod + - Renamed LinkBattleNet to LinkBattleNetAccount and UnlinkBattleNet to UnlinkBattleNetAccount in the Client API + - Added ExportVersionedCatalog to the Economy API. Removed UploadVersionedCatalog. + - Added the following Data Connection management calls to the Events API: + - DeleteDataConnection + - GetDataConnection + - ListDataConnections + - SetDataConnection + - SetDataConnectionActive + - Added the following calls to the Server API: + - LinkBattleNetAccount + - LoginWithBattleNet + - UnlinkBattleNetAccount + - Expanded Economy API catalog items with real-money price details across multiple storefronts + - Added error codes for new service errors + +## 250425 + +Date: April 25, 2025 + + - Added Battle.net identity provider support with the following calls to the Client API: + - GetPlayFabIDsFromBattleNetAccountIds + - LinkBattleNet + - LoginWithBattleNet + - UnlinkBattleNet + - Added GetPlayFabIDsFromBattleNetAccountIds to the Server API + - Added the following login calls to the Server API: + - LoginWithAndroidDeviceID + - LoginWithCustomID + - LoginWithIOSDeviceID + - Added the following calls to the Economy API: + - CompleteVersionedCatalogUpload + - CreateVersionedCatalogUploadURL + - GetVersionedCatalogUploadStatus + - Added the following TrueSkill calls to the Multiplayer API: + - GetPlayerSkillForConditions + - GetPlayerSkillForConditionsFromModel + - Added error codes for new service errors + +## 250328 + +Date: March 28, 2025 + + - Added DeleteVersionedCatalog to the Economy API + - Added RestrictInvitesToLobbyOwner to the Multiplayer API + - Added error codes for new service errors + +## 250314 + +Date: March 14, 2025 + + - Added the following calls to the Economy API: + - GetVersionedCatalogItem + - UploadVersionedCatalog + - Added TrueSkill-related types to the Multiplayer API + - Added error codes for new service errors + +## 250228 + +Date: February 28, 2025 + + - Cleaned up API spec schema formatting across all APIs. No functional API changes. + +## 250214 + +Date: February 14, 2025 + + - Removed the following deprecated calls from the Economy API: + - Inventory/AddVirtualCurrencies + - Inventory/ConsumeInventoryItems + - Catalog/EvaluateDropTable + - Inventory/GetAccessTokens + - Inventory/GetReceiptIssuerCertificateAsJwk + - Inventory/GetReceiptIssuerCertificateAsPem + - Inventory/GetVirtualCurrencies + - Inventory/GrantInventoryItems + - Catalog/PurchaseItemByFriendlyId + - Catalog/PurchaseItemById + - Inventory/Redeem + - Inventory/RefreshSubscriptions + - Inventory/SetInventoryItems + - Inventory/SetVirtualCurrencies + - Inventory/SubtractVirtualCurrencies + - Inventory/UpdateInventoryItemsProperties + - Added UpdateLeaderboardDefinition and UpdateStatisticDefinition to the Progression API + - Added NextReset field to leaderboard definitions in the Progression API + - Added error codes for new service errors + +## 250117 + +Date: January 17, 2025 + + - Added error codes for new service errors + - Added TransactionId to UpdateStatisticsRequest in the Progression API \ No newline at end of file diff --git a/playfab-docs/release-notes/index.md b/playfab-docs/release-notes/index.md index 478ad6e70..a1da27b06 100644 --- a/playfab-docs/release-notes/index.md +++ b/playfab-docs/release-notes/index.md @@ -1,22 +1,46 @@ --- -title: PlayFab Services SDK Release Notes 2025 -author: amccalib -description: PlayFab Services SDK Release Notes for 2025. -ms.author: andmcc -ms.date: 01/28/2025 +title: PlayFab Services SDK Release Notes 2026 +author: stevenLizano29 +description: PlayFab Services SDK Release Notes for 2026. +ms.author: v-stevenroj +ms.date: 03/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, development, release, apis, features ms.localizationpriority: medium --- -# PlayFab Services SDK Release Notes 2025 +# PlayFab Services SDK Release Notes 2026 > [!NOTE] > For release notes about service releases and product updates, see the [release notes](https://github.com/PlayFab/PlayFab/releases) section on [PlayFab's public GitHub repository](https://github.com/PlayFab/PlayFab) -## 250117 +## 260227 -Date: January 17, 2025 +Date: February 27, 2026 + - Added ProductDisabledForTitle error code to multiple calls across the Client, Server, and Admin APIs + - Added error codes for new service errors + +## 260213 + +Date: February 13, 2026 + + - Added AddOrUpdateContactEmail to the Server API + - Added PubSub connection lifetime extension support to the Multiplayer API + - Added error codes for new service errors + +## 260123 + +Date: January 23, 2026 + + - Removed GetMicrosoftStoreAccessTokens from the Economy API + - Added error codes for new service errors + +## 260109 + +Date: January 9, 2026 + + - Added the following calls to the Server API: + - UnlinkFacebookAccount + - UnlinkFacebookInstantGamesId - Added error codes for new service errors - - Added TransactionId to UpdateStatisticsRequest in the Progression API \ No newline at end of file diff --git a/playfab-docs/release-notes/toc.yml b/playfab-docs/release-notes/toc.yml index f889885f0..e42d3ab68 100644 --- a/playfab-docs/release-notes/toc.yml +++ b/playfab-docs/release-notes/toc.yml @@ -1,5 +1,7 @@ -- name: 2025 SDK Release Notes +- name: 2026 SDK Release Notes href: ./index.md +- name: 2025 SDK Release Notes + href: ./2025.md - name: 2024 SDK Release Notes href: ./2024.md - name: 2023 SDK Release Notes diff --git a/playfab-docs/whats-new/toc.yml b/playfab-docs/whats-new/toc.yml index 016339489..a735f94d7 100644 --- a/playfab-docs/whats-new/toc.yml +++ b/playfab-docs/whats-new/toc.yml @@ -3,8 +3,10 @@ items: ## href: whats-new.md - name: Previous Release Notes items: - - name: 2025 SDK Release Notes + - name: 2026 SDK Release Notes href: /playfab-docs/release-notes/index.md + - name: 2025 SDK Release Notes + href: /playfab-docs/release-notes/2025.md - name: Lobby and Matchmaking SDK Release Notes href: ../multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md - name: PlayFab Party SDK Release Notes From 8d68888c81fa41b9ab49f919ed0981ef4ebeb865 Mon Sep 17 00:00:00 2001 From: Taojunshen Date: Wed, 11 Mar 2026 06:11:09 +0800 Subject: [PATCH 69/76] 3/10/2026 Publish (#2850) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * PlayStream event documentation update Party (#2793) * Add Party PS events * PlayStream event documentation: fix Party events (#2817) * Adding missing event and removing one * Adding missing events * Revert "Adding missing events" This reverts commit 2844ac6f6b4f0fa54c79fc2a6ca5ecedc8afb87a. * pf-review-edits-pr-2813-02-17-2026-01 --------- Co-authored-by: Raul Gomez Rodriguez Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Removing internal events * Addressing PR Feedback * Updating author and ms.author * Cleaning up unrelated Networking changes in index.md * Adding events to toc.yml file * Removing unwanted events * Removing extra space --------- Co-authored-by: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * pf-review-edits-61014764-02-24-2026-01 (#2836) * Rename-playfab-remove-azure (#2810) * Remove all instances of "Azure PlayFab" in preference of "PlayFab" * Correcting all branding mismatches of "Playfab" to "PlayFab" * Further corrections on branding * Update playfab-docs/multiplayer/servers/directly-debugging-game-servers.md Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * pf-review-edits-pr-2810-02-19-2026-01 * pf-review-edits-pr-2810-02-19-2026-02 * pf-review-edits-pr-2810-02-19-2026-03 * Fix formatting in PlayFab fundamentals summary and description Acrolinx --------- Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Update instructions for disabling multiple events (#2839) Co-authored-by: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> * PFMultiplayer SDK v1.8.7 Release Notes (#2840) * Release notes PFM 1.8.7 * PR feedback --------- Co-authored-by: Berni Mora Escobar * ✨ MicrosoftStore redeem docs (#2828) Co-authored-by: Ernesto Cortes Groman Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Add v1.10.17 release notes (#2834) * Update uhfHeaderId in docfx.json for upcoming all up Gaming L2 Nav Header (#2844) Update uhfHeaderId in docfx.json for upcoming all up Gaming L2 Nav Header Note: Playfab headers are embedded / accessible within the new header so no information previously on Playfab header is lost. Reminder to self / doc team, this change is not to be merged until it is confirmed that the Nav update is also live from the MS Learn team. * Add UI callbacks doc, clarify XAsyncBlock behavior during sync failures (#2845) - Add new ui-callbacks.md covering all five callback types, state machine model, response APIs, and platform override behavior - Update offline.md to clarify XAsyncBlock deferral during retry loops - Trim quickstart.md Step 4 to cross-reference ui-callbacks.md - Add UI Callbacks entry to toc.yml Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add missing releases notes from jan 2025 to mar 2026 (#2849) --------- Co-authored-by: ronnyparedesc <113482725+ronnyparedesc@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez <108555472+rgomez391@users.noreply.github.com> Co-authored-by: Raul Gomez Rodriguez Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Co-authored-by: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> Co-authored-by: anaisnlawson Co-authored-by: Berni Mora <93845766+BerniME@users.noreply.github.com> Co-authored-by: Berni Mora Escobar Co-authored-by: Ernesto Cortes Groman Co-authored-by: Ernesto Cortes Groman Co-authored-by: eduardobadilla07 Co-authored-by: edigonzales-microsoft Co-authored-by: Andy McCalib Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Steven Rojas Lizano --- .../title-permission-policy-changed.md | 2 +- .../entity-executed-cloud-script.md | 2 +- .../player-executed-cloudscript.md | 2 +- .../CloudScript/title-added-cloudscript.md | 2 +- .../client-authentication-completed.md | 32 +++ .../Networking/client-connected-to-network.md | 35 +++ .../client-initialization-completed.md | 26 ++ .../Networking/client-network-created.md | 42 ++++ .../Networking/client-network-destroyed.md | 33 +++ .../client-network-information-received.md | 35 +++ .../Networking/client-request-failed.md | 31 +++ .../Networking/data-received-by-clients.md | 27 +++ .../events/Networking/data-sent-by-clients.md | 27 +++ .../moderation-service-request-count.md | 27 +++ .../player-disconnected-from-network.md | 28 +++ .../unity-client-initialization-completed.md | 34 +++ .../unreal-client-initialization-completed.md | 37 +++ playfab-docs/api-references/events/index.md | 55 ++++- playfab-docs/api-references/toc.yml | 28 ++- playfab-docs/breadcrumb/toc.yml | 64 +++-- playfab-docs/community/index.yml | 2 +- playfab-docs/community/leaderboards/index.md | 8 +- .../leaderboards/leaderboards-cloudscript.md | 22 +- .../leaderboards-linked-to-stats.md | 2 +- .../export-data/data-connection-azure-blob.md | 40 ++-- playfab-docs/data-analytics/index.yml | 2 +- .../ingest-data/opt-in-events.md | 6 +- ...etting-started-with-data-explorer-basic.md | 2 +- .../legacy/insights/best-practices.md | 2 +- .../legacy/insights/overview.md | 30 +-- .../legacy/insights/performance-retention.md | 2 +- .../legacy/insights/scheduled-scaling.md | 2 +- playfab-docs/docfx.json | 2 +- .../economy-monetization/economy-v2/faq.md | 2 +- .../economy-v2/fraud-prevention/quickstart.md | 4 +- .../marketplace-integrations/google.md | 2 +- .../marketplace-integrations/microsoft.md | 177 ++++++++++++++ .../marketplace-integrations/overview.md | 9 +- .../marketplace-integrations/toc.yml | 2 + .../marketplace-redemption/microsoft.md | 156 ++++++++++++ .../marketplace-redemption/overview.md | 14 +- .../marketplace-redemption/toc.yml | 2 + .../economy-v2/quickstart.md | 4 +- .../craftingGame/crafting-game-environment.md | 2 +- .../economy-v2/ugc/index.yml | 2 +- .../economy-monetization/economy/index.yml | 2 +- playfab-docs/economy-monetization/index.yml | 2 +- playfab-docs/get-started/index.yml | 10 +- playfab-docs/get-started/what-is-playfab.md | 12 +- playfab-docs/identity/index.yml | 2 +- .../anonymous-login.md | 38 +-- .../kongregate-html5.md | 20 +- .../platform-specific-authentication/toc.yml | 2 +- playfab-docs/index.yml | 8 +- .../gamemanager/reference.md | 72 +++--- .../live-service-management/index.yml | 2 +- playfab-docs/multiplayer/index.yml | 2 +- .../multiplayer/lobby/create-a-lobby.md | 2 +- playfab-docs/multiplayer/lobby/index.md | 8 +- ...and-matchmaking-real-time-notifications.md | 2 +- .../lobby/lobby-getting-started.md | 2 +- .../lobby-and-matchmaking-release-notes.md | 8 + .../lobby-matchmaking-logging.md | 8 +- .../lobby-matchmaking-sdks.md | 8 +- .../multiplayer-unity-sdk-getting-started.md | 4 +- .../multiplayer/lobby/lobby-properties.md | 22 +- .../functions/pfmultiplayerfindlobbies.md | 2 +- .../pfmatchmaking/pfmatchmaking_members.md | 4 +- .../structs/pfmultiplayerport.md | 4 +- .../structs/pfmultiplayerserverdetails.md | 8 +- .../PlayFab.Multiplayer/MultiplayerPort.md | 4 +- .../MultiplayerPort/MultiplayerPort.md | 2 +- .../MultiplayerServerDetails.md | 8 +- .../MultiplayerServerDetails.md | 6 +- .../PlayFabMultiplayerSDK.md | 4 +- .../unity-multiplayer-api-reference/index.md | 4 +- .../multiplayer/matchmaking/quickstart.md | 14 +- .../networking/concepts-port-usage.md | 12 +- playfab-docs/multiplayer/networking/index.md | 8 +- .../multiplayer/networking/party-features.md | 8 +- .../multiplayer/networking/party-logging.md | 14 +- .../networking/party-playstream-events.md | 2 +- .../multiplayer/networking/party-samples.md | 4 +- .../multiplayer/networking/party-sdks.md | 8 +- .../party-unreal-engine-oss-quickstart.md | 2 +- .../multiplayer/networking/release-notes.md | 138 ++++++----- .../networking/unreal-release-notes.md | 4 +- .../servers/deploying-linux-based-builds.md | 2 +- .../directly-debugging-game-servers.md | 2 +- .../multiplayer/servers/os-patch-updates.md | 18 +- .../servers/server-samples-resources.md | 2 +- .../multiplayer/servers/server-sdks.md | 8 +- .../multiplayer/servers/server-terms.md | 28 +-- .../multiplayer/servers/vmstartupscript.md | 2 +- .../player-progression/game-saves/offline.md | 21 +- .../game-saves/quickstart.md | 45 +--- .../player-progression/game-saves/toc.yml | 2 + .../game-saves/ui-callbacks.md | 175 ++++++++++++++ playfab-docs/player-progression/index.yml | 2 +- .../player-progression/statistics/index.md | 8 +- playfab-docs/pricing/Meters/meters.md | 4 +- playfab-docs/pricing/Meters/profile-reads.md | 126 +++++----- playfab-docs/pricing/Meters/profile-writes.md | 4 +- playfab-docs/release-notes/2025.md | 226 ++++++++++++++++++ playfab-docs/release-notes/index.md | 42 +++- playfab-docs/release-notes/toc.yml | 4 +- playfab-docs/sdks/c-sharp/index.md | 2 +- playfab-docs/sdks/c/index.md | 4 +- playfab-docs/sdks/playfab-sdk-intro.md | 6 +- playfab-docs/whats-new/toc.yml | 4 +- 110 files changed, 1777 insertions(+), 523 deletions(-) create mode 100644 playfab-docs/api-references/events/Networking/client-authentication-completed.md create mode 100644 playfab-docs/api-references/events/Networking/client-connected-to-network.md create mode 100644 playfab-docs/api-references/events/Networking/client-initialization-completed.md create mode 100644 playfab-docs/api-references/events/Networking/client-network-created.md create mode 100644 playfab-docs/api-references/events/Networking/client-network-destroyed.md create mode 100644 playfab-docs/api-references/events/Networking/client-network-information-received.md create mode 100644 playfab-docs/api-references/events/Networking/client-request-failed.md create mode 100644 playfab-docs/api-references/events/Networking/data-received-by-clients.md create mode 100644 playfab-docs/api-references/events/Networking/data-sent-by-clients.md create mode 100644 playfab-docs/api-references/events/Networking/moderation-service-request-count.md create mode 100644 playfab-docs/api-references/events/Networking/player-disconnected-from-network.md create mode 100644 playfab-docs/api-references/events/Networking/unity-client-initialization-completed.md create mode 100644 playfab-docs/api-references/events/Networking/unreal-client-initialization-completed.md create mode 100644 playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/microsoft.md create mode 100644 playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/microsoft.md create mode 100644 playfab-docs/player-progression/game-saves/ui-callbacks.md create mode 100644 playfab-docs/release-notes/2025.md diff --git a/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md b/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md index 0434064f5..f287f2d6e 100644 --- a/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md +++ b/playfab-docs/api-references/events/ApiAccessPolicy/title-permission-policy-changed.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # title_permission_policy_changed -This event is triggered when an update occurs to a a title's permission policies. +This event is triggered when an update occurs to a title's permission policies. ## Properties diff --git a/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md b/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md index 1e8ad14aa..d11f611b6 100644 --- a/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md +++ b/playfab-docs/api-references/events/CloudScript/entity-executed-cloud-script.md @@ -18,7 +18,7 @@ This event is optionally triggered when a CloudScript function is executed by ca |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that is useful for debugging.| +|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that's useful for debugging.| |EntityChain|String|The chain of ownership for this entity.| |EntityLineage|[EntityLineage](../data-types/entitylineage.md)|Entities that this entity is a child of.| |FunctionName|String|Name of the CloudScript function that was called.| diff --git a/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md b/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md index 4c526f032..08579b360 100644 --- a/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md +++ b/playfab-docs/api-references/events/CloudScript/player-executed-cloudscript.md @@ -18,7 +18,7 @@ This event is optionally triggered when a CloudScript function is executed, eith |Name|Type|Description| | :--------------------|:-------------------|:----------------------| -|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that is useful for debugging.| +|CloudScriptExecutionResult|[ExecuteCloudScriptResult](../data-types/executecloudscriptresult.md)|Result of the CloudScript function, including diagnostic information that's useful for debugging.| |FunctionName|String|Name of the CloudScript function that was called.| |TitleId|String|The ID of the title to which this player event applies.| diff --git a/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md b/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md index bc7b41782..18f22de08 100644 --- a/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md +++ b/playfab-docs/api-references/events/CloudScript/title-added-cloudscript.md @@ -21,7 +21,7 @@ This event is triggered when new CloudScript is uploaded to PlayFab. |DeveloperId|String|| |Published|Boolean|Whether the CloudScript that was uploaded is live.| |Revision|int32|Revision number of the CloudScript file that was added.| -|ScriptNames|[]|Names of the individual script files modified. Currently this is just 'CloudScript.js' but later we will support multiple files.| +|ScriptNames|[]|Names of the individual script files modified. Currently this is just 'CloudScript.js' but later we'll support multiple files.| |UserId|String|| |Version|int32|Version number of the CloudScript file that was added.| diff --git a/playfab-docs/api-references/events/Networking/client-authentication-completed.md b/playfab-docs/api-references/events/Networking/client-authentication-completed.md new file mode 100644 index 000000000..d990a6cc1 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-authentication-completed.md @@ -0,0 +1,32 @@ +--- +title: client_authentication_completed +author: raulalbertog +description: client_authentication_completed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_authentication_completed + +This event is triggered when client authentication is completed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier at the time of this event.| +|AuthDurationInMs|uint32|The duration of the isolated authentication operation in milliseconds.| +|TotalDurationInMs|uint32|The duration of the authentication operation and all associated operations queued before it in milliseconds.| +|LocalConnectionId|uint32|A local identifier to disambiguate multiple connections to the same network from a single client.| +|Result|int32|The PartyStateChangeResult of the operation.| +|ResultMessage|String|A human-readable representation of the Result value.| +|ErrorDetail|uint32|The PartyError error detail code.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-connected-to-network.md b/playfab-docs/api-references/events/Networking/client-connected-to-network.md new file mode 100644 index 000000000..e43473039 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-connected-to-network.md @@ -0,0 +1,35 @@ +--- +title: client_connected_to_network +author: raulalbertog +description: client_connected_to_network event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_connected_to_network + +This event is triggered when a client connects to a network. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier.| +|RegionName|String|The region name associated with the underlying relay for the network.| +|HostName|String|The hostname of the relay the client is connecting to.| +|Port|uint16|The port the client is connecting to.| +|ConnectDurationInMs|uint32|The duration of the isolated connection operation in milliseconds.| +|TotalDurationInMs|uint32|The duration of the connection operation and all associated operations queued before it in milliseconds.| +|LocalConnectionId|uint32|A local identifier to disambiguate multiple connections to the same network from a single client.| +|Result|int32|The PartyStateChangeResult of the operation.| +|ResultMessage|String|A human-readable representation of the Result value.| +|ErrorDetail|uint32|The PartyError error detail code.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-initialization-completed.md b/playfab-docs/api-references/events/Networking/client-initialization-completed.md new file mode 100644 index 000000000..d8baf8f87 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-initialization-completed.md @@ -0,0 +1,26 @@ +--- +title: client_initialization_completed +author: raulalbertog +description: client_initialization_completed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_initialization_completed + +This event is triggered when client initialization is completed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|BuildId|String|The identifier of the build that produced this binary.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-network-created.md b/playfab-docs/api-references/events/Networking/client-network-created.md new file mode 100644 index 000000000..a024cc84a --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-network-created.md @@ -0,0 +1,42 @@ +--- +title: client_network_created +author: raulalbertog +description: client_network_created event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_network_created + +This event is triggered when a client network is created. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier.| +|RegionName|String|The region name associated with the newly created network. Empty if the creation failed.| +|ServerId|String|The ServerId field from the PlayFab RequestPartyResponse.| +|VmId|String|The VmId field from the PlayFab RequestPartyResponse.| +|DurationInMs|uint32|The duration of this request in milliseconds.| +|Result|int32|The PartyStateChangeResult of the operation.| +|ResultMessage|String|A human-readable representation of the Result value.| +|ErrorDetail|uint32|The PartyError error detail code.| +|RegionCount|uint32|The count of regions specified when creating the network.| +|MaxUserCount|uint32|The maximum user count specified in the network configuration.| +|MaxDeviceCount|uint32|The maximum device count specified in the network configuration.| +|MaxUsersPerDeviceCount|uint32|The maximum users per device count specified in the network configuration.| +|MaxDevicesPerUserCount|uint32|The maximum devices per user count specified in the network configuration.| +|MaxEndpointsPerDeviceCount|uint32|The maximum endpoints per device count specified in the network configuration.| +|DirectPeerConnectivityOptions|int32|The direct peer connectivity options specified when creating the network.| +|RequestedRelayVersion|String|The requested relay protocol version.| +|RequestedRelayBuildAliasId|String|The requested relay build alias ID.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-network-destroyed.md b/playfab-docs/api-references/events/Networking/client-network-destroyed.md new file mode 100644 index 000000000..342af177a --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-network-destroyed.md @@ -0,0 +1,33 @@ +--- +title: client_network_destroyed +author: raulalbertog +description: client_network_destroyed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_network_destroyed + +This event is triggered when a client network is destroyed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier at the time it was destroyed.| +|RegionName|String|The region name associated with the underlying relay for the network.| +|HostName|String|The relay's hostname.| +|Port|uint16|The relay's port.| +|LocalConnectionId|uint32|A local identifier to disambiguate multiple connections to the same network from a single client.| +|Reason|int32|The PartyDestroyedReason that the network was destroyed.| +|ReasonMessage|String|A human-readable representation of the Reason value.| +|ErrorDetail|uint32|The PartyError error detail code.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-network-information-received.md b/playfab-docs/api-references/events/Networking/client-network-information-received.md new file mode 100644 index 000000000..db236fe29 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-network-information-received.md @@ -0,0 +1,35 @@ +--- +title: client_network_information_received +author: raulalbertog +description: client_network_information_received event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_network_information_received + +This event is triggered when client network information is received. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|NetworkIdentifier|String|The network's unique identifier.| +|NetworkInformationDurationInMs|uint32|The duration of the connection operation up to the point of receiving the network information, in milliseconds.| +|TotalDurationInMs|uint32|The duration of the connection operation, receiving the network information, and all associated operations queued before it in milliseconds.| +|MaxUserCount|uint32|The maximum user count specified in the network configuration.| +|MaxDeviceCount|uint32|The maximum device count specified in the network configuration.| +|MaxUsersPerDeviceCount|uint32|The maximum users per device count specified in the network configuration.| +|MaxDevicesPerUserCount|uint32|The maximum devices per user count specified in the network configuration.| +|MaxEndpointsPerDeviceCount|uint32|The maximum endpoints per device count specified in the network configuration.| +|NetworkDirectPeerConnectivityOptions|int32|The direct peer connectivity options specified in the network configuration.| +|LocalDeviceDirectPeerConnectivityOptions|int32|The direct peer connectivity options specified by the local device when connecting to the network.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/client-request-failed.md b/playfab-docs/api-references/events/Networking/client-request-failed.md new file mode 100644 index 000000000..794f89704 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/client-request-failed.md @@ -0,0 +1,31 @@ +--- +title: client_request_failed +author: raulalbertog +description: client_request_failed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# client_request_failed + +This event is triggered when a client request fails. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|The client-generated globally unique identifier of this instance of the Party library.| +|RequestType|String|The type of the request that failed.| +|HttpStatusCode|int32|The HTTP status code of the failed request.| +|HttpStatusString|String|The HTTP status string of the failed request.| +|PlayFabErrorCode|int32|The PlayFab error code.| +|ErrorName|String|The PlayFab error name.| +|ErrorMessage|String|The PlayFab error message.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/data-received-by-clients.md b/playfab-docs/api-references/events/Networking/data-received-by-clients.md new file mode 100644 index 000000000..eb1ee2736 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/data-received-by-clients.md @@ -0,0 +1,27 @@ +--- +title: data_received_by_clients +author: raulalbertog +description: data_received_by_clients event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# data_received_by_clients + +This event is triggered when data is received by clients. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|LoginIdentityProvider|String|The identity provider used for login.| +|RegionName|String|The region name associated with the relay.| +|DataSizeInBytes|uint64|The total data size in bytes received by clients from the cloud service.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/data-sent-by-clients.md b/playfab-docs/api-references/events/Networking/data-sent-by-clients.md new file mode 100644 index 000000000..fd55f6da5 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/data-sent-by-clients.md @@ -0,0 +1,27 @@ +--- +title: data_sent_by_clients +author: raulalbertog +description: data_sent_by_clients event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# data_sent_by_clients + +This event is triggered when data is sent by clients. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|LoginIdentityProvider|String|The identity provider used for login.| +|RegionName|String|The region name associated with the relay.| +|DataSizeInBytes|uint64|The total data size in bytes sent by clients to the cloud service.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/moderation-service-request-count.md b/playfab-docs/api-references/events/Networking/moderation-service-request-count.md new file mode 100644 index 000000000..3ae8d17cf --- /dev/null +++ b/playfab-docs/api-references/events/Networking/moderation-service-request-count.md @@ -0,0 +1,27 @@ +--- +title: moderation_service_request_count +author: raulalbertog +description: moderation_service_request_count event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# moderation_service_request_count + +This event is triggered when moderation service request count is reported. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|LoginIdentityProvider|String|The identity provider used for login.| +|RegionName|String|The region name associated with the relay.| +|DataSizeInBytes|uint64|The total count of moderation service requests.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/player-disconnected-from-network.md b/playfab-docs/api-references/events/Networking/player-disconnected-from-network.md new file mode 100644 index 000000000..8c9267502 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/player-disconnected-from-network.md @@ -0,0 +1,28 @@ +--- +title: player_disconnected_from_network +author: raulalbertog +description: player_disconnected_from_network event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_disconnected_from_network + +This event is triggered when a player disconnects from a network. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|LoginIdentityProvider|String|The identity provider used for login.| +|RegionName|String|The region name associated with the relay.| +|ChatDurationInMs|uint64|The total duration of chat time in milliseconds.| +|ConnectedDurationInMs|uint64|The total duration the player was connected to the network in milliseconds.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/unity-client-initialization-completed.md b/playfab-docs/api-references/events/Networking/unity-client-initialization-completed.md new file mode 100644 index 000000000..084656ea5 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/unity-client-initialization-completed.md @@ -0,0 +1,34 @@ +--- +title: unity_client_initialization_completed +author: raulalbertog +description: unity_client_initialization_completed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# unity_client_initialization_completed + +This event is triggered when Unity client initialization is completed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|A unique identifier for this game session.| +|PartyVersion|String|The version of the Party native library.| +|PartyUnityVersion|String|The version of the Party Unity SDK.| +|UnityVersion|String|The version of the Unity engine.| +|OSName|String|The name of the operating system.| +|DeviceMake|String|The device manufacturer name.| +|DeviceModel|String|The device model name.| +|Platform|String|The Unity runtime platform.| +|AppName|String|The application product name.| +|AppVersion|String|The application version.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Networking/unreal-client-initialization-completed.md b/playfab-docs/api-references/events/Networking/unreal-client-initialization-completed.md new file mode 100644 index 000000000..84fcbe122 --- /dev/null +++ b/playfab-docs/api-references/events/Networking/unreal-client-initialization-completed.md @@ -0,0 +1,37 @@ +--- +title: unreal_client_initialization_completed +author: raulalbertog +description: unreal_client_initialization_completed event. +ms.author: raulalbertog +ms.date: 02/19/2019 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# unreal_client_initialization_completed + +This event is triggered when Unreal client initialization is completed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ClientInstanceId|String|A unique identifier for this game session.| +|PartyVersion|String|The version of the Party native library.| +|UnrealEngineVersion|String|The version of the Unreal Engine.| +|PlatformSDKVersion|String|The version of the platform SDK.| +|OSSPlayFabVersion|String|The version of the OnlineSubsystemPlayFab plugin.| +|TitleID|String|The PlayFab title ID.| +|OSName|String|The name of the operating system.| +|OSVersion|String|The version of the operating system.| +|DeviceMake|String|The device manufacturer name.| +|DeviceModel|String|The device model name.| +|PlatformName|String|The name of the platform.| +|AppName|String|The application name.| +|AppVersion|String|The application version.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 51dea43a3..116d89d00 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -14,7 +14,7 @@ ms.localizationpriority: medium These are the built-in PlayStream events which are automatically generated by PlayFab Game Services APIs and written to the event pipeline. In addition to these events, you can create your own custom events using the [WriteEvents](xref:titleid.playfabapi.com.events.playstreamevents.writeevents) API. -Each event type has a set of properties that are included as part of event's data wherever it is sent. You can view these properties and build rules for triggering actions based on their values in the PlayStream tab of the Game Manager. +Each event type has a set of properties that are included as part of event's data wherever it's sent. You can view these properties and build rules for triggering actions based on their values in the PlayStream tab of the Game Manager. ## AdPlacement @@ -28,7 +28,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a player opens an ad. - [player_ad_rewarded](AdPlacement/player-ad-rewarded.md) - This event is triggered when a player recieves an ad reward. + This event is triggered when a player receives an ad reward. - [player_ad_started](AdPlacement/player-ad-started.md) This event is triggered when a player starts an ad. @@ -44,7 +44,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when an API Features setting is changed for the title. - [title_permission_policy_changed](ApiAccessPolicy/title-permission-policy-changed.md) - This event is triggered when an update occurs to a a title's permission policies. + This event is triggered when an update occurs to a title's permission policies. ## CloudScript @@ -98,7 +98,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a task is deleted. - [title_exceeded_limit](Extension/title-exceeded-limit.md) - This event is triggererd when a title exceeds a service limit and receives an error. + This event is triggered when a title exceeds a service limit and receives an error. - [title_limit_changed](Extension/title-limit-changed.md) This event is triggered when a title changes a service limit. @@ -325,7 +325,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when an item moderation state is changed. - [item_publish_requested](catalogv2/item-publish-requested.md) - This event is triggered when an publishing is started. + This event is triggered when publishing is started. - [item_purchased](catalogv2/item-purchased.md) This event is triggered when an item is purchased. @@ -340,7 +340,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a review is reported. - [reviews_takedown_requested](catalogv2/reviews-takedown-requested.md) - Event trigged when a takedown of reviews is requested. + This event is triggered when a takedown of reviews is requested. ## Character @@ -399,13 +399,54 @@ Each event type has a set of properties that are included as part of event's dat - [gamesave_version_marked_known_good](GameSave/gamesave-version-marked-known-good.md) This event is triggered when a game save version is marked as known good. +## Networking + +- [client_authentication_completed](Networking/client-authentication-completed.md) + This event is triggered when client authentication is completed. + +- [client_connected_to_network](Networking/client-connected-to-network.md) + This event is triggered when a client connects to a network. + +- [client_initialization_completed](Networking/client-initialization-completed.md) + This event is triggered when client initialization is completed. + +- [client_network_created](Networking/client-network-created.md) + This event is triggered when a client network is created. + +- [client_network_destroyed](Networking/client-network-destroyed.md) + This event is triggered when a client network is destroyed. + +- [client_network_information_received](Networking/client-network-information-received.md) + This event is triggered when client network information is received. + +- [client_request_failed](Networking/client-request-failed.md) + This event is triggered when a client request fails. + +- [data_received_by_clients](Networking/data-received-by-clients.md) + This event is triggered when data is received by clients. + +- [data_sent_by_clients](Networking/data-sent-by-clients.md) + This event is triggered when data is sent by clients. + +- [moderation_service_request_count](Networking/moderation-service-request-count.md) + This event is triggered when moderation service request count is reported. + +- [player_disconnected_from_network](Networking/player-disconnected-from-network.md) + This event is triggered when a player disconnects from a network. + +- [unity_client_initialization_completed](Networking/unity-client-initialization-completed.md) + This event is triggered when Unity client initialization is completed. + +- [unreal_client_initialization_completed](Networking/unreal-client-initialization-completed.md) + This event is triggered when Unreal client initialization is completed. + ## Partner - [display_name_filtered](Partner/display-name-filtered.md) This event is triggered when a display name is filtered by community sift. - [player_display_name_filtered](Partner/player-display-name-filtered.md) - This event is triggered when a display name is filtered by community sift only if there is an associated player EntityId for the event. + This event is triggered when a display name is filtered by community sift only if there's an associated player EntityId for the event. - [player_photon_session_authenticated](Partner/player-photon-session-authenticated.md) This event is triggered when a player connects to a Photon Cloud application and authenticates with PlayFab using Photon custom authentication. diff --git a/playfab-docs/api-references/toc.yml b/playfab-docs/api-references/toc.yml index 38e494193..36dc3f475 100644 --- a/playfab-docs/api-references/toc.yml +++ b/playfab-docs/api-references/toc.yml @@ -442,6 +442,32 @@ href: events/Leaderboards/character-statistic-changed.md - name: character_statistic_deleted href: events/Leaderboards/character-statistic-deleted.md + - name: client_authentication_completed + href: events/Networking/client-authentication-completed.md + - name: client_connected_to_network + href: events/Networking/client-connected-to-network.md + - name: client_initialization_completed + href: events/Networking/client-initialization-completed.md + - name: client_network_created + href: events/Networking/client-network-created.md + - name: client_network_destroyed + href: events/Networking/client-network-destroyed.md + - name: client_network_information_received + href: events/Networking/client-network-information-received.md + - name: client_request_failed + href: events/Networking/client-request-failed.md + - name: data_received_by_clients + href: events/Networking/data-received-by-clients.md + - name: data_sent_by_clients + href: events/Networking/data-sent-by-clients.md + - name: moderation_service_request_count + href: events/Networking/moderation-service-request-count.md + - name: player_disconnected_from_network + href: events/Networking/player-disconnected-from-network.md + - name: unity_client_initialization_completed + href: events/Networking/unity-client-initialization-completed.md + - name: unreal_client_initialization_completed + href: events/Networking/unreal-client-initialization-completed.md - name: entity_rank_on_leaderboard_version_ended href: events/Leaderboards/entity-rank-on-leaderboard-version-ended.md - name: leaderboard_version_ended @@ -461,4 +487,4 @@ - name: Global API method error codes href: global-api-method-error-codes.md - name: HTTP response status codes - href: http-response-status-codes.md + href: http-response-status-codes.md \ No newline at end of file diff --git a/playfab-docs/breadcrumb/toc.yml b/playfab-docs/breadcrumb/toc.yml index 0b4ca3ed8..309e333fb 100644 --- a/playfab-docs/breadcrumb/toc.yml +++ b/playfab-docs/breadcrumb/toc.yml @@ -1,37 +1,33 @@ items: -- name: Azure +- name: PlayFab tocHref: /gaming/playfab/ - topicHref: /azure/ + topicHref: /gaming/playfab/ items: - - name: PlayFab - tocHref: /gaming/playfab/ - topicHref: /gaming/playfab/ - items: - - name: Fundamentals - topicHref: /gaming/playfab/get-started/ - - name: Fundamentals - topicHref: /gaming/playfab/whats-new/ - - name: Fundamentals - topicHref: /gaming/playfab/demo-game/ - - name: Fundamentals - topicHref: /gaming/playfab/resources/ - - name: Fundamentals - topicHref: /gaming/playfab/pricing/ - - name: Fundamentals - topicHref: /gaming/playfab/sdks/ - - name: Live service management - topicHref: /gaming/playfab/live-service-management/ - - name: Fundamentals - topicHref: /gaming/playfab/api-references/ - - name: Identity - topicHref: /gaming/playfab/identity/ - - name: Economy, Monetization, & UGC. - topicHref: /gaming/playfab/economy-monetization/ - - name: Multiplayer - topicHref: /gaming/playfab/multiplayer/ - - name: Community - topicHref: /gaming/playfab/community/ - - name: Player progression - topicHref: /gaming/playfab/player-progression/ - - name: Game Data - topicHref: /gaming/playfab/data-analytics/ + - name: Fundamentals + topicHref: /gaming/playfab/get-started/ + - name: Fundamentals + topicHref: /gaming/playfab/whats-new/ + - name: Fundamentals + topicHref: /gaming/playfab/demo-game/ + - name: Fundamentals + topicHref: /gaming/playfab/resources/ + - name: Fundamentals + topicHref: /gaming/playfab/pricing/ + - name: Fundamentals + topicHref: /gaming/playfab/sdks/ + - name: Live service management + topicHref: /gaming/playfab/live-service-management/ + - name: Fundamentals + topicHref: /gaming/playfab/api-references/ + - name: Identity + topicHref: /gaming/playfab/identity/ + - name: Economy, Monetization, & UGC. + topicHref: /gaming/playfab/economy-monetization/ + - name: Multiplayer + topicHref: /gaming/playfab/multiplayer/ + - name: Community + topicHref: /gaming/playfab/community/ + - name: Player progression + topicHref: /gaming/playfab/player-progression/ + - name: Game Data + topicHref: /gaming/playfab/data-analytics/ diff --git a/playfab-docs/community/index.yml b/playfab-docs/community/index.yml index e0875faf9..540538db9 100644 --- a/playfab-docs/community/index.yml +++ b/playfab-docs/community/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Community documentation +title: PlayFab Community documentation summary: PlayFab Community is a set of cross-platform tools and services that enable game creators to build engaging social experiences and foster long term player connections and communities. metadata: diff --git a/playfab-docs/community/leaderboards/index.md b/playfab-docs/community/leaderboards/index.md index 684107747..9f5f74232 100644 --- a/playfab-docs/community/leaderboards/index.md +++ b/playfab-docs/community/leaderboards/index.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Leaderboards overview +title: PlayFab Leaderboards overview author: braulioal -description: Learn about Azure PlayFab Leaderboard. +description: Learn about PlayFab Leaderboard. ms.author: braulioal ms.date: 09/01/2024 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, leaderboard, stats ms.localizationpriority: medium --- -# Azure PlayFab Leaderboards overview +# PlayFab Leaderboards overview -Azure Playfab Leaderboards is a cross-platform service that creates a sorted list of players with the purpose +PlayFab Leaderboards is a cross-platform service that creates a sorted list of players with the purpose of ranking them by scores. Leaderboards can be used as a standalone service or be linked with Statistics (so that updates to statistics feed into the entries on the leaderboard). ![PlayFab Leaderboards Architecture](media/leaderboards-relationship.png) diff --git a/playfab-docs/community/leaderboards/leaderboards-cloudscript.md b/playfab-docs/community/leaderboards/leaderboards-cloudscript.md index ed552009a..8021d97c3 100644 --- a/playfab-docs/community/leaderboards/leaderboards-cloudscript.md +++ b/playfab-docs/community/leaderboards/leaderboards-cloudscript.md @@ -13,20 +13,20 @@ ms.localizationpriority: medium # Leaderboards using Azure Functions In this tutorial, you'll learn how to implement leaderboards using Cloudscript, specifically through [Azure Functions](../../live-service-management/service-gateway/automation/cloudscript-af/index.md). -This approach is particularly powerful because it enables you to create custom server-side logic without requiring client updates. +This approach is powerful because it enables you to create custom server-side logic without requiring client updates. By defining leaderboard-related logic within an Azure Function, your client can invoke that function to execute the code. If changes are needed later, you can update the Azure Function independently—often without modifying the client—depending on the complexity of the update. ## Prerequisites -To follow this tutorial you need to have: -- A PlayFab account, if you don't have one you can create it [here](https://developer.playfab.com/). -- An Azure subscription, if you don't have one you can create it [here](https://azure.microsoft.com/free/). +To follow this tutorial, you need: +- A PlayFab account. If you don't have one, you can create it [here](https://playfab.com/). +- An Azure subscription. If you don't have one, you can create it [here](https://azure.microsoft.com/free/). For more details on how to create an Azure Function check this guide. [Create your first function in Azure using Visual Studio](https://learn.microsoft.com/azure/azure-functions/functions-create-your-first-function-visual-studio) -## Create a Leaderboard using Azure Functions +## Create a leaderboard using Azure Functions -In this section we're going to create a simple leaderboard that will allow us to submit scores and retrieve the top scores. +In this section, we're going to create a leaderboard that allows you to submit scores and retrieve the top scores. ``` C# [Function("LeaderboardExample")] @@ -82,12 +82,12 @@ public async Task RunAsync([HttpTrigger(AuthorizationLevel.Ano } ``` -- This function attribute ```[Function("LeaderboardExample")]``` defines the name of the function, in this case "LeaderboardExample". +- This function attribute ```[Function("LeaderboardExample")]``` defines the name of the function, in this case `LeaderboardExample`. - The function is triggered by an HTTP request, as indicated by the ```[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")]``` attribute. This means that the function can be accessed via HTTP GET and POST methods without any authentication. -- Within the function, we set the PlayFab Title ID and Developer Secret Key to authenticate our requests to PlayFab services. You can change the way you want to access this values based on what fits best for your particular case and security requirements. +- Within the function, we set the PlayFab Title ID and Developer Secret Key to authenticate our requests to PlayFab services. You can change the way you want to access these values based on what fits best for your particular case and security requirements. - The function checks if the query parameter "leaderboardName" is provided in the request. - Then we call the method ```LoginAsTitleEntity``` to authenticate as a title entity, which is necessary to create leaderboard definitions. -- Finally, we call the method ```CreateLeaderboardDefinitionAsync``` to create a leaderboard definition with the provided name. To find more about creation of leaderboard you can check [Create basic leaderboard](create-basic-leaderboard.md) and [Doing more with leaderboards](doing-more-with-leaderboards.md). +- Finally, we call the method ```CreateLeaderboardDefinitionAsync``` to create a leaderboard definition with the provided name. To find more about creation of leaderboard, you can check [Create basic leaderboard](create-basic-leaderboard.md) and [Doing more with leaderboards](doing-more-with-leaderboards.md). The RunAsync method serves as the entry point for your Azure Function. From there, you can define and call additional methods to build out your custom game logic. How you handle errors or interact with multiple PlayFab services is entirely up to you, giving you full flexibility in your implementation. @@ -97,8 +97,8 @@ Additionally, you can configure automation rules to trigger this Azure Function - [Doing more with leaderboards](doing-more-with-leaderboards.md). - [Create basic leaderboard](create-basic-leaderboard.md). - [Manual tiers](manual-tiers.md). -- [Limits ](limits-leaderboards.md). -- [Quota ](quota-leaderboards.md). +- [Limits](limits-leaderboards.md). +- [Quota](quota-leaderboards.md). - [Seasonal leaderboards](seasonal-leaderboards.md). - [Ranking players by statistics](leaderboards-linked-to-stats.md). - [Add contextual data to leaderboards](metadata-leaderboards.md). diff --git a/playfab-docs/community/leaderboards/leaderboards-linked-to-stats.md b/playfab-docs/community/leaderboards/leaderboards-linked-to-stats.md index bf584b8ec..a61550237 100644 --- a/playfab-docs/community/leaderboards/leaderboards-linked-to-stats.md +++ b/playfab-docs/community/leaderboards/leaderboards-linked-to-stats.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Ranking players by statistics In this tutorial, we're going to learn how to use both Leaderboards and Statistics services together. The end result is that, when a statistic is updated on an entity, is automatically reflected on the corresponding leaderboard. -For more information about Azure PlayFab Statistics, see [Statistics Overview]([Azure PlayFab Statistics overview](../../player-progression/statistics/index.md)). +For more information about PlayFab Statistics, see [Statistics Overview]([PlayFab Statistics overview](../../player-progression/statistics/index.md)). Let's start with an example of a shooter game that uses both services. Here we're going to take advantage of the diff --git a/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md b/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md index e50aff8f9..4eea129ea 100644 --- a/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md +++ b/playfab-docs/data-analytics/export-data/data-connection-azure-blob.md @@ -13,19 +13,19 @@ ms.localizationpriority: medium First, you need an Azure subscription and a storage account. -For existing PlayFab and Azure customers, you can create a storage container on the [Azure portal](https://ms.portal.azure.com/#allservices) and get started with Data Connections on [Azure PlayFab](https://developer.playfab.com). +For existing PlayFab and Azure customers, you can create a storage container on the [Azure portal](https://ms.portal.azure.com/#allservices) and get started with Data Connections on [PlayFab](https://developer.playfab.com/en-US/sign-up). For existing PlayFab who are new to Azure, you can sign up for an [Azure subscription](https://ms.portal.azure.com/). -> [!Note] +> [!NOTE] > Make sure to create your Storage Account in the West US 2, otherwise, egress cost will be applied to your storage account. You can configure up to three Azure Blob Storage accounts in the WestUS2 region. ## Setting up your Storage in Azure -For PlayFab to ingest data in your storage account, container details along with authorization using a SAS token are required. To create a SAS token using the Microsoft Azure portal, follow the steps below. +For PlayFab to ingest data in your storage account, container details along with authorization using a SAS token are required. To create a SAS token using the Microsoft Azure portal, use the following steps. -> [!Note] -> A Storage Account with a restricted network is not supported. All networks must be allowed in the firewall. +> [!NOTE] +> A storage account with a restricted network isn't supported. You must allow all networks in the firewall. ### Option 1: Create the SAS token on the container level. > [!Important] @@ -45,48 +45,48 @@ For PlayFab to ingest data in your storage account, container details along with - Specify the signed key **Start** and **Expiry** times. - Select **Generate SAS token and URL**. - The **Blob SAS token** query string appears in the lower area of the window. -- Copy and paste the **Blob SAS token** values into a **secure location for use in the Azure PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. +- Copy and paste the **Blob SAS token** values into a **secure location for use in the PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. -### Option 2: Create the SAS token on the account level. +### Option 2: Create the SAS token at the account level > [!Important] -> Generate and retrieve the shared access signature for your storage account itself. +> Generate and retrieve the shared access signature for your storage account. - In the [Azure portal](https://ms.portal.azure.com/#allservices), select **Your storage account** -- Select a **Shared access signature** from the list under **Security + Networking**. +- Select **Shared access signature** from the list under **Security + Networking**. - Define **Services** by selecting **blob** and clearing other checkboxes. - Define **Resource Type** by selecting **Container** and **Object** (clear other checkboxes). -- Make sure the **Create**, **Write**, and **List** are selected. +- Make sure the **Create**, **Write**, and **List** permissions are selected. - Specify the signed key **Start** and **Expiry** times. - Select **Generate SAS token and URL**. - The Blob SAS token query string appears in the lower area of the window. -- Copy and paste the **Blob SAS token** values into a **secure location for use in the Azure PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. +- Copy and paste the **Blob SAS token** values into a **secure location for use in the PlayFab Data Connections**. It's displayed only once and can't be retrieved after the window is closed. ![Screenshot of SAS token on the account level - Option 2](media/SAS-token-on-the-account-level.png "SAS token on the account level - Option 2") ## Create an Azure Blob Data Connection in PlayFab -### Step 1: Navigate to the data connections tab +### Step 1: Navigate to the Data Connections tab ![Screenshot of PlayFab data connections tab](media/navigate-to-data-connections-tab.png "PlayFab data connections tab") - Login to PlayFab and navigate to your title. -- Click on the “Data” section in the left-hand menu -- Click on the “Data Connections” tab +- Select the **Data** section in the left-hand menu. +- Select the **Data Connections** tab. ### Step 2: Configure a new Data Connection -- Click “New Connection” button. -- Choose the “Destination Type” to be “Azure Blob Storage” -- Populate the fields using the following values +- Select **New Connection**. +- Choose **Azure Blob Storage** as the **Destination Type**. +- Enter the following values for each field: | Value | Details | |:-----------|:-----------| -|Name | The friendly name of your data connection. This name will allow you to find the data connection later to edit it. Put a descriptive name here. +|Name | The friendly name of your data connection. This name allows you to find the data connection later to edit it. Put a descriptive name here. | Account name | The Azure Storage Account. | | Container name | The Azure Storage Account Container. | | Sas token | Either the SAS token generated by the container, or the Blob SAS token query string. | ![Screenshot of configuring and ADX data connection](media/configure-new-data-connection-blob.PNG "ADX data connection configuration") -> [!Note] -> We recommend using a table name that does not exist. If you use an existing table and the schema is not what PlayFab is expecting, then the schema will be modified. +> [!NOTE] +> We recommend using a table name that doesn't exist. If you use an existing table and the schema isn't what PlayFab is expecting, then the schema will be modified. diff --git a/playfab-docs/data-analytics/index.yml b/playfab-docs/data-analytics/index.yml index cd03df823..5bce4b403 100644 --- a/playfab-docs/data-analytics/index.yml +++ b/playfab-docs/data-analytics/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab data and analytics documentation +title: PlayFab data and analytics documentation summary: PlayFab data and analytics helps you manage game data. It provides reporting functions for generating weekly reports and trends, tools for segmenting data and running experiments, and data management tools for ingesting, exporting, and managing data. # < 160 chars metadata: diff --git a/playfab-docs/data-analytics/ingest-data/opt-in-events.md b/playfab-docs/data-analytics/ingest-data/opt-in-events.md index b7d56f995..f24221e1c 100644 --- a/playfab-docs/data-analytics/ingest-data/opt-in-events.md +++ b/playfab-docs/data-analytics/ingest-data/opt-in-events.md @@ -78,9 +78,9 @@ To preview event data, select the graph icon next to any event. A data explorer To disable multiple events at once: 1. Select **Bulk Edit Events** in the header. -1. Choose **Set all PlayStream events to none** or **Set all telemetry events to none** (or both). -1. Select **Apply** to make the changes. -1. Review the toast notification and the unsaved changes indicator, then **Save** or **Discard Changes** as needed. +1. Choose **Turn off emission for all PlayStream events** or **Turn off emission for all telemetry events** (or both). +1. Select **Bulk edit** to make the changes. +1. **Save** or **Discard Changes** as needed. ## Save configuration changes diff --git a/playfab-docs/data-analytics/learn-data/data-explorer/getting-started-with-data-explorer-basic.md b/playfab-docs/data-analytics/learn-data/data-explorer/getting-started-with-data-explorer-basic.md index 24f5dde9e..d42f33acc 100644 --- a/playfab-docs/data-analytics/learn-data/data-explorer/getting-started-with-data-explorer-basic.md +++ b/playfab-docs/data-analytics/learn-data/data-explorer/getting-started-with-data-explorer-basic.md @@ -58,7 +58,7 @@ The table shows the Event Name, Timestamp (UTC), Player ID, and Event Data (via #### What's the sum of order totals this week? ![Order totals sum this week](media/ExplorerBasic_Query_3.png) -#### Are Playfab limits being exceeded? +#### Are PlayFab limits being exceeded? ![Title limits exceeded this week](media/ExplorerBasic_Query_4.png) ### Multi Condition Queries diff --git a/playfab-docs/data-analytics/legacy/insights/best-practices.md b/playfab-docs/data-analytics/legacy/insights/best-practices.md index d474eae28..4996f3eaf 100644 --- a/playfab-docs/data-analytics/legacy/insights/best-practices.md +++ b/playfab-docs/data-analytics/legacy/insights/best-practices.md @@ -103,7 +103,7 @@ Here we examine some best practices for using PlayFab Insights and address the m | Events per entity | 8,000 per second | Exceeding this limit results in a `PerEntityEventRateLimitExceeded` error. An entity most often represents an individual player, but can also be a player group or title. | | Max payload size | 10,240 bytes (10 KB) | | - If you run into any of these limits, contact the Playfab Support team for assistance. In the upper right-hand corner of Game Manager select the question mark icon, then select **Contact Us**. + If you run into any of these limits, contact the PlayFab Support team for assistance. In the upper right-hand corner of Game Manager select the question mark icon, then select **Contact Us**. ### I get an error "Query execution has exceeded the allowed limits" when I try to run a query diff --git a/playfab-docs/data-analytics/legacy/insights/overview.md b/playfab-docs/data-analytics/legacy/insights/overview.md index 22fe2f46f..ee2f34065 100644 --- a/playfab-docs/data-analytics/legacy/insights/overview.md +++ b/playfab-docs/data-analytics/legacy/insights/overview.md @@ -12,48 +12,48 @@ ms.localizationpriority: medium # What is PlayFab Insights? > [!NOTE] -> PlayFab Insights Management was deprecated on December 11th, 2023. We recommend using [Azure Data Explorer (ADX) Connections](../../export-data/data-connection-adx.md) to manage your performance and cost going forward. If your title is still using **Insights**, continue to see this article for feature details. For more information, see [Insights Deprecation Blog](https://developer.microsoft.com/en-us/games/articles/2023/09/playfab-insights-management-to-be-deprecated-starting-december-11/). +> PlayFab Insights Management was deprecated on December 11, 2023. We recommend using [Azure Data Explorer (ADX) Connections](../../export-data/data-connection-adx.md) to manage your performance and cost going forward. If your title is still using **Insights**, continue to see this article for feature details. For more information, see [Insights Deprecation Blog](https://developer.microsoft.com/en-us/games/articles/2023/09/playfab-insights-management-to-be-deprecated-starting-december-11/). -PlayFab Insights is a managed data environment, giving you instant access to your games data without the need for additional engineering. Unlike other hosted data solutions Insights requires no setup, no GDPR work, and no extra engineering. Simply use PlayFab services and your data is available. Automatically ingest and scale, connect external visualization tools, and query freely. +PlayFab Insights is a managed data environment, giving you instant access to your games data without the need for additional engineering. Unlike other hosted data solutions Insights requires no setup, no GDPR work, and no extra engineering. Use PlayFab services and your data is available. Automatically ingest and scale, connect external visualization tools, and query freely. -## Key Features +## Key features Insights key features revolve around data cluster management, data retention, ingestion options, and connectivity to outside tools. -### Automatic Ingestion +### Automatic ingestion PlayFab services automatically fire Playstream events. Any events fired by PlayFab services or created through our SDK are automatically routed to your Insights cluster. There's no need to worry about defining schema or DDL from automatic events. However, the option for sending your own custom events is available. For more information about sending custom events, see the [Custom event overview](../../ingest-data/playstream-overview.md) of Generating PlayStream events. -### Change Your Performance Level To Meet Your Needs +### Change your performance level to meet your needs ![Insights Slider](media/insights-slider.png) Match your cluster performance to your needs minute by minute. Slide your performance level up or down or alternatively schedule your cluster to have different performance levels automatically using scheduled tasks. See [Performance Level & Retention](performance-retention.md) for details. -### Schedule Your Performance Level +### Schedule your performance level ![Scheduled Scaling](media/insights-schedule.png) Use standard cron expressions to automatically scale your cluster up and down during known times. See [Scheduled Scaling](scheduled-scaling.md) for details. -### Keep Your Data as Long as You Need +### Keep your data as long as you need ![Storage and Retention](media/insights-retention.png) Never delete your data or clear your data out every 30 days, whatever is needed for your studio. See [Performance Level & Retention](performance-retention.md) for details. -### Connect Outside Tools +### Connect outside tools Connect Power BI or Grafana for visualization, automate data jobs with Python or Azure Data Factory, explore your data with Azure Data Explorer. See [Connectivity](../connectivity/index.md) for details. -### Export Original or Cleaned Data +### Export original or cleaned data Use the automated export service to export all your data to Azure Blob or AWS S3. See [Exporting Data](export.md) for details. -### Bring Your Own Datasets +### Bring your own datasets Ingest your own custom datasets with [Management Commands](management-commands.md). Merge your custom Playstream events, standard Playstream events, and custom uploaded data to create more robust datasets. -### GDPR Compliant -Standard reporting is tracked and GDPR compliant. Call the playfab GDPR delete request and we'll do the rest. Have custom data you need to delete? No problem, use the [Management Commands](management-commands.md) to maintain your custom data. +### GDPR compliant +Standard reporting is tracked and GDPR compliant. Call the PlayFab GDPR delete request and we'll do the rest. Have custom data you need to delete? No problem, use the [Management Commands](management-commands.md) to maintain your custom data. -## Getting Started with PlayFab Insights -PlayFab Insights is available to all studios right out of the box. The only thing needed to get started is some data. Implement any PlayFab service and you get playstream events automatically sent to your *Insights* or you [can send telemetry directly using PlayFab API calls](xref:titleid.playfabapi.com.events.playstreamevents). Once you have some data check out [Data Explorer](../../export-data/data-connection-quickstart.md). +## Getting started with PlayFab Insights +PlayFab Insights is available to all studios right out of the box. The only thing needed to get started is some data. Implement any PlayFab service and you get playstream events automatically sent to your *Insights* or you [can send telemetry directly using PlayFab API calls](xref:titleid.playfabapi.com.events.playstreamevents). After you have some data, check out [Data Explorer](../../export-data/data-connection-quickstart.md). ## What services are powered by Insights? -PlayFab Insights powers various features and functionality across Game Manager. Adjusting the performance level affects the following across your title: +PlayFab Insights powers various features and functionality across Game Manager. Adjusting the performance level affects the following areas across your title: * Data * Data Explorer (Preview) * Event Export diff --git a/playfab-docs/data-analytics/legacy/insights/performance-retention.md b/playfab-docs/data-analytics/legacy/insights/performance-retention.md index d932d2626..4804cff0c 100644 --- a/playfab-docs/data-analytics/legacy/insights/performance-retention.md +++ b/playfab-docs/data-analytics/legacy/insights/performance-retention.md @@ -1,7 +1,7 @@ --- title: Performance and retention author: joannaleecy -description: Performance and retention for playfab insights +description: Performance and retention for PlayFab insights ms.author: jenelleb ms.date: 02/28/2020 ms.topic: article diff --git a/playfab-docs/data-analytics/legacy/insights/scheduled-scaling.md b/playfab-docs/data-analytics/legacy/insights/scheduled-scaling.md index 6fb59b57c..688eae4ab 100644 --- a/playfab-docs/data-analytics/legacy/insights/scheduled-scaling.md +++ b/playfab-docs/data-analytics/legacy/insights/scheduled-scaling.md @@ -1,7 +1,7 @@ --- title: Scheduled Scaling author: joannaleecy -description: Scheduled Scaling for playfab insights +description: Scheduled Scaling for PlayFab insights ms.author: jenelleb ms.date: 02/28/2020 ms.topic: article diff --git a/playfab-docs/docfx.json b/playfab-docs/docfx.json index 34969a045..1e6b3daeb 100644 --- a/playfab-docs/docfx.json +++ b/playfab-docs/docfx.json @@ -33,7 +33,7 @@ "overwrite": [], "externalReference": [], "globalMetadata": { - "uhfHeaderId": "MSDocsHeader-PlayFab", + "uhfHeaderId": "MSDocsHeader-Gaming", "breadcrumb_path": "/gaming/playfab/breadcrumb/toc.json", "feedback_system": "Standard", "feedback_product_url": "https://community.playfab.com/index.html", diff --git a/playfab-docs/economy-monetization/economy-v2/faq.md b/playfab-docs/economy-monetization/economy-v2/faq.md index 1dfc1985b..b8e46a159 100644 --- a/playfab-docs/economy-monetization/economy-v2/faq.md +++ b/playfab-docs/economy-monetization/economy-v2/faq.md @@ -54,7 +54,7 @@ If your title isn’t live yet, the process is easier but there are differences **Q: Does Economy V2 support all of the features from Economy V1 (Legacy)?** -**A:** No, Economy V2 doesn’t have full parity with all of the features PlayFab supports in V1 (Legacy). Some of these features never received the adoption we hoped for in Playfab. Others were lacking the depth and surface area needed to really help developers implement them in their games. Some we plan to deliver in future updates. Specifically today Economy V2 doesn't support PlayFab style Coupons, Limited Items, Recharge Item Rates, Drop Tables, or Store Support with Segments. +**A:** No, Economy V2 doesn’t have full parity with all of the features PlayFab supports in V1 (Legacy). Some of these features never received the adoption we hoped for in PlayFab. Others were lacking the depth and surface area needed to really help developers implement them in their games. Some we plan to deliver in future updates. Specifically today Economy V2 doesn't support PlayFab style Coupons, Limited Items, Recharge Item Rates, Drop Tables, or Store Support with Segments. ## Marketplace and platform integrations diff --git a/playfab-docs/economy-monetization/economy-v2/fraud-prevention/quickstart.md b/playfab-docs/economy-monetization/economy-v2/fraud-prevention/quickstart.md index dab61b133..c2d35cd43 100644 --- a/playfab-docs/economy-monetization/economy-v2/fraud-prevention/quickstart.md +++ b/playfab-docs/economy-monetization/economy-v2/fraud-prevention/quickstart.md @@ -32,11 +32,11 @@ To give those entries meaning, we need to mirror them in the PlayFab Catalog. Mi Each Bundle can be linked to one or more Partner Marketplace Products by adding an AlternateId to it. The AlternateId is the link between PlayFab and any external IAP Market. When your title calls Redeem for a given player entity, we pass this ID up to the IAP Market to check. The general flow is: 1. Create 1 (or more) real world offers in the Microsoft Store -1. Populate the Add-ons in PlayFab with IAP Market calling permissions and create corresponding Bundles in Playfab that link to the offers you created +1. Populate the Add-ons in PlayFab with IAP Market calling permissions and create corresponding Bundles in PlayFab that link to the offers you created 1. Call `RedeemMicrosoftStoreInventoryItems` > [!NOTE] -> Unlike previous incarnations of Playfab, in the new system you just create one bundle offer, and then you add each market SKU that needs to reference into the AlternateId list. You don’t need to create a new Item for each IAP market. +> Unlike previous incarnations of PlayFab, in the new system you just create one bundle offer, and then you add each market SKU that needs to reference into the AlternateId list. You don’t need to create a new Item for each IAP market. ### Step 1 - Setting up your marketplace integration diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/google.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/google.md index 53e3012d6..1c9f2bc4e 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/google.md +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/google.md @@ -108,7 +108,7 @@ It's time to move on to the [Google Play Console](https://play.google.com/consol ![Add app permissions](../../media/marketplace-integrations/google/add-app-permissions.png) -6. From the list of apps, choose the one you want your account to be linked to. In this case, it's **Economy V2 Playfab Test App**. Once selected, press **Apply**. +6. From the list of apps, choose the one you want your account to be linked to. In this case, it's **Economy V2 PlayFab Test App**. Once selected, press **Apply**. ![App selection](../../media/marketplace-integrations/google/app-selection.png) diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/microsoft.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/microsoft.md new file mode 100644 index 000000000..7bcb51d98 --- /dev/null +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/microsoft.md @@ -0,0 +1,177 @@ +--- +title: Marketplace integration - Microsoft Store +author: ernestoc +description: How to redeem Microsoft Store in-app purchases through PlayFab Economy v2 +ms.author: ernestoc +ms.date: 02/23/2026 +ms.topic: tutorial +ms.service: azure-playfab +keywords: playfab, integration, marketplace, microsoft store, xbox, redeem, consumable, durable +ms.localizationpriority: medium +--- + +# Marketplace integration: Microsoft Store + +This tutorial shows you how to redeem Microsoft Store in-app purchases (including Xbox) through PlayFab Economy v2 using the [RedeemMicrosoftStoreInventoryItems](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) API. + +By the end of this tutorial, you: + +- Created an add-on in Partner Center +- Configured the required Partner Center and PlayFab settings +- Linked your Microsoft Store product to a PlayFab catalog Bundle +- Called the Redeem API and verified items in your player's inventory + +## Prerequisites + +1. A [Partner Center](https://partner.microsoft.com/) account with access to your app. +2. An app already created in Partner Center. +3. A Title already created in [Game Manager](https://developer.playfab.com/). +4. The player calling the Redeem API must be authenticated to PlayFab using an Xbox Live identity (for example, via `LoginWithXbox`). Players authenticated with other identity types (such as CustomID or email) do not have the Xbox context required for this flow. + +## Supported product types + +The `RedeemMicrosoftStoreInventoryItems` API supports the following Microsoft Store product types: + +- **Developer-managed consumable** — Products that can be purchased, used, and purchased again (for example, in-game currency packs). The game service is responsible for tracking fulfillment. +- **Durable** — Products that are purchased once and owned permanently (for example, DLC, expansion packs, season passes, or cosmetic items). + +> [!IMPORTANT] +> **Store-managed consumables are not supported.** PlayFab Economy v2 cannot redeem Store-managed consumables. If your add-on is configured as a Store-managed consumable, the Redeem API returns an HTTP 200 response with empty results and no error, making the issue difficult to diagnose. + +## Step 1: Create your add-on in Partner Center + +1. Sign in to [Partner Center](https://partner.microsoft.com/) and navigate to your app. +2. Under **Add-ons**, select **Create a new add-on**. +3. Select the appropriate product type: + - **Developer-managed consumable** for items that can be repurchased (currency, consumable packs). + - **Durable** for one-time purchases (DLC, season passes, cosmetic unlocks). +4. Complete the add-on configuration (pricing, descriptions, and so on) and submit it. + +> [!IMPORTANT] +> When creating a Developer-managed consumable, Partner Center displays a warning that reads: *"Xbox requires consumables to be managed, so do not use this option and create a 'managed consumable' add-on instead. If you have any questions, contact your Microsoft representative."** +> +> This warning reflects general Xbox platform guidance and **does not apply to the PlayFab redemption flow**. Developer-managed consumables work correctly on Xbox when used with PlayFab's `RedeemMicrosoftStoreInventoryItems` API. You can safely proceed with this product type. + +5. After creating your add-on, note the **Store ID**—the alphanumeric string (for example, `9NBLGGH42CFD`) shown in Partner Center. Use this value for PlayFab, **not** the developer-defined Product ID, or the add-on name. + +For more information on product types, see [Choosing the right product type](/gaming/gdk/docs/store/commerce/getting-started/xstore-choosing-the-right-product-type). + +## Step 2: Configure Product Group, Dev Studio, and Business Partner ID + +This step configures the delegated Xbox Security Token Service (XSTS) token flow that PlayFab uses to query the Microsoft Store Collections API on behalf of the player. + +> [!WARNING] +> The Product Group, Dev Studio, and Business Partner ID configuration is the most commonly missed step. Without it, the Redeem API call succeeds (HTTP 200) but the Collections API returns zero items—resulting in empty `Succeeded`, `Failed`, and `TransactionIds` arrays with no error message. + +1. In [Partner Center](https://partner.microsoft.com/), navigate to **Developer Settings** > **Xbox Live** > **Web Services** and generate a Business Partner Certificate if you have not already. +2. Navigate to **Developer Settings** > **Xbox Live** > **Business Partner** and note the **Business Partner ID** that matches the web service your relying party is tied to. +3. Create a **Dev Studio** (or use an existing one) and set its **Dev Studio ID** to match the **Business Partner ID** from step 2. If the Dev Studio already has a different ID, create a new Dev Studio rather than changing the existing value. Changing it can break existing services. +4. Create a **Product Group** and assign it to the Dev Studio from step 3. +5. Add your game product **and** all of your add-ons to the **Included in this product group** list. Items must be explicitly moved from the "available" side to the "included" side. +6. Select **Save**. +7. Navigate to your game's **Xbox Settings** page and confirm the linked **Business Partner** matches the one from step 2. +8. **Republish** your game product and all add-ons to the Microsoft Store in your target sandbox or RETAIL environment. + +For the full configuration walkthrough, see [Configure products with delegated authentication (XSTS tokens)](/gaming/gdk/docs/store/commerce/service-to-service/xstore-authenticating-your-service#additional-configuration-required-to-view-and-manage-products-with-delegated-authentication-xsts-tokens). + +## Step 3: Enable the Xbox Network add-on in Game Manager + +The Xbox Network add-on links your Partner Center product to your PlayFab title and enables Xbox token validation for Microsoft Store redemption. + +1. Open [Game Manager](https://developer.playfab.com/) and select your **Title**. +2. Select **Add-ons** from the left navigation menu. +3. Locate and select the **Xbox Network** add-on (labeled **Distribute for Xbox**). +4. Select the correct **Seller ID** from the dropdown. If you do not see the correct Seller ID, select **Sign in with a different partner center account**. +5. Select your **Partner Center Product ID** from the dropdown and confirm the **Xbox Live Title ID** (decimal) matches what you see in Partner Center under **Xbox services** > **Xbox Settings**. +6. Select **Install Xbox Network** to save the configuration. + +For more details, see [Xbox Live add-on configuration](/gaming/playfab/identity/player-identity/platform-specific-authentication/xbox-live-add-on). + +> [!NOTE] +> Game Manager also has a separate **Microsoft Store** add-on page (also under **Add-ons**). While it does not require configuration, it contains useful guidance including confirmation of supported product types and details on the Dev Studio ID and Business Partner ID setup. + +## Step 4: Create a PlayFab Bundle with Marketplace Mapping + +To link your Microsoft Store product to your PlayFab catalog, create a **Bundle** with a **Marketplace Mapping** (AlternateId). + +1. In [Game Manager](https://developer.playfab.com/), navigate to **Economy** > **Catalog (V2)** > **Bundles**. +2. Select **New bundle** (or edit an existing one). +3. Under the **Marketplace Mapping** section, add a new mapping: + - Set the **Marketplace type** to `MicrosoftStore` (case-sensitive, must be exactly `MicrosoftStore`). + - Set the **value** to the exact **Store ID** from Partner Center (for example, `9NBLGGH42CFD`). Do not use the developer-defined Product ID or the add-on name. +4. Add the items you want the player to receive when this Bundle is redeemed (for example, in-game currency, virtual items). +5. **Publish** the Bundle. Unpublished (draft) Bundles are not matched during redemption. + +For more information on alternate IDs, see [Alternate IDs](/gaming/playfab/economy-monetization/economy-v2/catalog/content-types-tags-and-properties#alternate-ids). + +## Step 5: Acquire and provide the Xbox token + +When calling the [RedeemMicrosoftStoreInventoryItems](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) API, you must provide a valid Xbox token in the `XboxToken` parameter. + + +- If you are using the **GDK C API**, use: + + ```cpp + XUserGetTokenAndSignatureAsync // with method "POST", URL "https://playfabapi.com/", and empty body "" + ``` + +All three parameters (method, URL, and body) must be provided exactly as shown. An incorrectly obtained token causes the Collections API query to fail silently, returning empty results with no error. + +## Step 6: Test the integration + +Before considering your integration complete, verify the full end-to-end flow: + +1. Ensure your add-on is published to the sandbox or environment you are testing in. +2. Sign in as a test player using an Xbox Live identity and make a test purchase of the add-on through the Microsoft Store. The player must have an unredeemed purchase on their account before the Redeem API has anything to detect. +3. Call `RedeemMicrosoftStoreInventoryItems` with the player's `XboxToken`. +4. Verify the response contains entries in the `Succeeded` array and that the corresponding items appear in the player's PlayFab inventory. + +> [!NOTE] +> **Developer-managed consumable fulfillment:** After a Developer-managed consumable is redeemed, PlayFab automatically reports it as **fulfilled** (consumed) with the Microsoft Store on your behalf. The fulfillment step is necessary before the player can purchase the consumable again. If the consumable does not appear as fulfilled after a successful redemption, retry the `RedeemMicrosoftStoreInventoryItems` call. If the issue persists, escalate to the PlayFab team through your support channel. For details, see [Managing consumables and refunds](/gaming/gdk/docs/store/commerce/service-to-service/xstore-managing-consumables-and-refunds). + +## Troubleshooting + +If the `RedeemMicrosoftStoreInventoryItems` call returns successfully (HTTP 200) but the `Succeeded`, `Failed`, and `TransactionIds` arrays in the response are all empty, the Microsoft Store Collections API is not finding any matching items to redeem. A configuration issue typically causes this behavior. Check the following items: + +| Issue | Resolution | +|---|---| +| **Wrong product type** | Ensure the add-on is a **Developer-managed consumable** or **Durable**, not a Store-managed consumable. PlayFab does not support Store-managed consumables. | +| **Incorrect Store ID in PlayFab** | Confirm the Marketplace Mapping value matches the **Store ID** (alphanumeric string like `9NBLGGH42CFD`), not the developer-defined Product ID or add-on name. | +| **Bundle not published** | Publish the Bundle in your PlayFab catalog. Draft Bundles are not matched during redemption. | +| **Missing Product Group configuration** | Confirm your game and add-ons are included in a Product Group tied to the correct Dev Studio and Business Partner ID. The Product Group configuration is the most commonly missed step. See [Step 2](#step-2-configure-product-group-dev-studio-and-business-partner-id). | +| **Xbox Network add-on not configured** | Install and configure the Xbox Network add-on in Game Manager. See [Step 3](#step-3-enable-the-xbox-network-add-on-in-game-manager). | +| **No unredeemed purchase** | The player must have an unredeemed purchase of the product before the API can detect and redeem it. Make a test purchase first. | +| **Consumable not fulfilled** | PlayFab automatically fulfills Developer-managed consumables after redemption. If a consumable was redeemed once but does not redeem again, retry the `RedeemMicrosoftStoreInventoryItems` call. If the issue persists, escalate to the PlayFab team through your support channel. See [Managing consumables and refunds](/gaming/gdk/docs/store/commerce/service-to-service/xstore-managing-consumables-and-refunds). | +| **Sandbox mismatch** | Ensure the add-on is published to the same sandbox you are testing in. The Xbox token carries sandbox context, so both must match. | +| **Invalid Xbox token** | Verify the token is obtained with the correct parameters: method `POST`, URL `https://playfabapi.com/`, and an empty body string `""`. | +| **Player not authenticated with Xbox identity** | The player must be signed in to PlayFab using an Xbox Live identity (for example, via `LoginWithXbox`). Other identity types do not have the Xbox context required for redemption. | + +If the API returns an HTTP error (such as 400), check the error response for the following codes: + +| Error code | Description | +|---|---| +| `InvalidCatalogItemConfiguration` | The Bundle or Marketplace Mapping is misconfigured in the PlayFab catalog. | +| `InvalidXboxLiveToken` | The Xbox token is invalid, expired, or obtained with incorrect parameters. | +| `AccountNotLinked` | The player's PlayFab account is not linked to an Xbox Live identity. | +| `XboxInaccessible` | PlayFab cannot reach Xbox services. The error may be transient. | +| `XboxXASSExchangeFailure` | The XSTS token exchange failed. Verify your Business Partner and relying party configuration. | + +> [!TIP] +> If the call succeeds (HTTP 200) but returns empty results and all other configuration looks correct, check the Product Group configuration first. The Product Group step is the most commonly missed step. + +## Note on PC / Windows titles + +This tutorial covers the Xbox flow, which uses delegated XSTS tokens (passed via the `XboxToken` parameter). For **PC / Windows titles**, Microsoft recommends using User Store IDs with Microsoft Entra ID for service-to-service authentication instead. For more information, see [Requesting a User Store ID for service-to-service authentication](/gaming/gdk/docs/store/commerce/service-to-service/xstore-requesting-a-userstoreid) and [Authenticating your service — User Store IDs](/gaming/gdk/docs/store/commerce/service-to-service/xstore-authenticating-your-service#authenticating-through-microsoft-entra-id-and-user-store-ids). + +## See also + +- [RedeemMicrosoftStoreInventoryItems API reference](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) +- [Fraud prevention quickstart](/gaming/playfab/economy-monetization/economy-v2/fraud-prevention/quickstart) +- [Xbox Live add-on configuration](/gaming/playfab/identity/player-identity/platform-specific-authentication/xbox-live-add-on) +- [Authenticating your service (XSTS tokens)](/gaming/gdk/docs/store/commerce/service-to-service/xstore-authenticating-your-service) +- [Choosing the right product type](/gaming/gdk/docs/store/commerce/getting-started/xstore-choosing-the-right-product-type) +- [Consumable-based ecosystems](/gaming/gdk/docs/store/commerce/fundamentals/xstore-consumable-based-ecosystems) +- [Managing consumables and refunds](/gaming/gdk/docs/store/commerce/service-to-service/xstore-managing-consumables-and-refunds) +- [Alternate IDs (Marketplace Mapping)](/gaming/playfab/economy-monetization/economy-v2/catalog/content-types-tags-and-properties#alternate-ids) +- [How to successfully integrate an Apple app into Game Manager](apple.md) +- [How to successfully integrate a Google app into Game Manager](google.md) diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/overview.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/overview.md index ace6dec1c..5aea5df3c 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/overview.md +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/overview.md @@ -17,12 +17,12 @@ Marketplace integration with PlayFab allows you to connect your game to various ## Supported Marketplaces ### Steam -Integrate your game with Steam to leverage its extensive user base and robust infrastructure for in-game purchases. Configure the necessary settings in the Game Manager to connect your PlayFab title with Steam. +Integrate your game with Steam to use its extensive user base and robust infrastructure for in-game purchases. To connect your PlayFab title with Steam, configure the necessary settings in Game Manager. See our [Steam integration documentation](steam.md). ### Apple -Connect your game to the Apple App Store to enable in-app purchases for iOS users. Follow the integration steps in the Game Manager to ensure a smooth connection between PlayFab and Apple's marketplace. +To enable in-app purchases for iOS users, connect your game to the Apple App Store. To ensure a smooth connection between PlayFab and Apple's marketplace, follow the integration steps in Game Manager. See our [Apple App Store integration documentation](apple.md). @@ -31,4 +31,9 @@ Integrate with Google Play to offer in-app purchases for Android users. Set up t See our [Google Play Store integration documentation](google.md). +### Microsoft Store +To enable in-app purchases for Xbox and Windows users, integrate with the Microsoft Store. To link your PlayFab title with the Microsoft Store marketplace, configure the Xbox Network add-on in Game Manager and set up your Product Group in Partner Center. + +See our [Microsoft Store integration documentation](microsoft.md). + By integrating with these marketplaces, you can streamline the purchase process for your players and manage all transactions through PlayFab's unified platform. \ No newline at end of file diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/toc.yml b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/toc.yml index 917f0196f..55603507d 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/toc.yml +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-integrations/toc.yml @@ -5,5 +5,7 @@ items: href: google.md - name: Apple App Store href: apple.md + - name: Microsoft Store + href: microsoft.md - name: Steam href: steam.md \ No newline at end of file diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/microsoft.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/microsoft.md new file mode 100644 index 000000000..51fc5d121 --- /dev/null +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/microsoft.md @@ -0,0 +1,156 @@ +--- +title: Redemption with the Microsoft Store Marketplace +author: ernestoc +description: Set up PlayFab and the Microsoft Store to enable purchases and redemption on Xbox and Windows +ms.author: fprotti +ms.date: 02/22/2026 +ms.topic: tutorial +ms.service: azure-playfab +keywords: playfab, integration, marketplace, microsoft store, xbox, purchase, redemption +ms.localizationpriority: medium +--- + +# Set up PlayFab and the Microsoft Store to enable purchases + +This tutorial shows you how to: + +- Create a purchasable product in the Microsoft Store +- Map it to a PlayFab bundle +- Redeem purchased items into a player's inventory using the [RedeemMicrosoftStoreInventoryItems](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) API + +## Prerequisites + +1. A Title in PlayFab's [Game Manager](https://developer.playfab.com/). +2. An existing [integration between the selected Title and the Microsoft Store](../marketplace-integrations/microsoft.md), including: + - The **Xbox Network** add-on installed and configured in Game Manager. + - The **Product Group**, **Dev Studio**, and **Business Partner ID** configured in Partner Center. +3. A [Partner Center](https://partner.microsoft.com/) account with access to your app. +4. An app already created in Partner Center. +5. The player calling the Redeem API must be authenticated to PlayFab using an Xbox Live identity (for example, via `LoginWithXbox`). Players authenticated with other identity types (such as CustomID or email) do not have the Xbox context required for this flow. + +## Step 1: Create your add-on in Partner Center + +If you did not create an add-on in Partner Center as part of the [marketplace integration setup](../marketplace-integrations/microsoft.md#step-1-create-your-add-on-in-partner-center), follow these steps: + +1. Sign in to [Partner Center](https://partner.microsoft.com/) and navigate to your app. +2. Under **Add-ons**, select **Create a new add-on**. +3. Select the appropriate product type: + - **Developer-managed consumable** for items that can be repurchased (currency, consumable packs). + - **Durable** for one-time purchases (DLC, season passes, cosmetic unlocks). +4. Complete the add-on configuration (pricing, descriptions, and so on) and submit it. +5. After creating your add-on, note the **Store ID**—the alphanumeric string (for example, `9NBLGGH42CFD`) shown in Partner Center. Use this value for the marketplace mapping in PlayFab, **not** the developer-defined Product ID, or the add-on name. + +> [!IMPORTANT] +> **Store-managed consumables are not supported.** Only Developer-managed consumables and Durables work with the `RedeemMicrosoftStoreInventoryItems` API. Partner Center may display a warning suggesting that Developer-managed consumables are not supported on Xbox. This warning does not apply when using the PlayFab redemption flow. For more information, see [Choosing the right product type](/gaming/gdk/docs/store/commerce/getting-started/xstore-choosing-the-right-product-type). + +6. Publish the add-on to the sandbox or environment you intend to test in. + +## Step 2: Create a Bundle in Game Manager + +> [!NOTE] +> Before creating a bundle in **Game Manager**, create and publish the items you want to add to the bundle in your Catalog. If you need guidance on how to create an item, refer to [this step](../../tutorials/craftingGame/crafting-game-game-manager.md#step-4---create-your-first-item). + +To enable a marketplace mapping between **Game Manager** and the **Microsoft Store**, you need to create a **Bundle** in Game Manager. A bundle can contain multiple items with different quantities, and PlayFab adds them to the player's inventory once redeemed. Follow these steps: + +1. Go to [Game Manager](https://developer.playfab.com/) and navigate to your **Title**. +2. From the left navigation menu, choose **Engage** > **Economy**. +3. Select the **Bundles** tab. +4. Select **New bundle**. +5. Add any information you want to the **Bundle**, such as items and prices. +6. Scroll down to the end of the page and select **Save and publish** if you want it to be redeemable by players right away. Select **Save as draft** if you want to publish it at a later date. + +### Add items to your Bundle + +A bundle by itself does not grant any items to a player. You must first link items to it. Once redeemed, the bundle grants those items to the specific player. + +To add items to your bundle: + +1. Go to the **Items** section in edit mode. +2. Select **Add**. A window appears showing all your catalog items. +3. Find your desired item and select **Add** next to it. +4. Select the **Add** button at the bottom. + +## Step 3: Enable marketplace mapping + +To ensure that when a player purchases a product from the Microsoft Store it gets properly matched and assigned in Game Manager, you must configure the **Marketplace Mapping** on your Bundle. + +1. Navigate to your bundle in edit mode. +2. Scroll down to the **Marketplace Mapping** section. +3. From the **Marketplace** dropdown, select **MicrosoftStore** (case-sensitive, must be exactly `MicrosoftStore`). +4. For your **Marketplace ID**, use the exact **Store ID** from Partner Center (for example, `9NBLGGH42CFD`). Do **not** use the developer-defined Product ID. +5. Select the **+** at the right side of that row and **Save** your changes. + +> [!IMPORTANT] +> The Bundle must be **published** (not left as a draft) for it to be matched during redemption. The redemption API does not detect unpublished catalog items. + +For more information on alternate IDs, see [Alternate IDs](/gaming/playfab/economy-monetization/economy-v2/catalog/content-types-tags-and-properties#alternate-ids). + +## Step 4: Authenticate your player + +Before making a redemption call, you must ensure that the player is properly authenticated. For Xbox and Microsoft Store scenarios, use [LoginWithXbox](/rest/api/playfab/client/authentication/login-with-xbox) to authenticate the player with PlayFab. + +After a successful call to `LoginWithXbox`, PlayFab returns an `EntityToken` that you must use in the headers of your redemption call with the `X-EntityToken` key. + +## Step 5: Acquire the Xbox token + +The `RedeemMicrosoftStoreInventoryItems` API requires a valid Xbox token in the `XboxToken` parameter. This token is separate from the `EntityToken` used for authentication. + +- If you are using the **GDK C API**, use: + + ```cpp + XUserGetTokenAndSignatureAsync // with method "POST", URL "https://playfabapi.com/", and empty body "" + ``` + +All three parameters (method, URL, and body) must be provided exactly as shown. An incorrectly obtained token causes the Microsoft Store Collections API query to fail silently, returning no items. + +## Step 6: Make a purchase + +The player must purchase the add-on from the Microsoft Store before you can redeem it through PlayFab. This purchase can be made through the Xbox or Windows Store interface. + +> [!NOTE] +> If you are testing in a sandbox environment, ensure the player account and the add-on are both published to the same sandbox. The player must have an **unredeemed purchase** on their account for the redemption API to find items to redeem. + +## Step 7: Redeem the purchase + +With your player authenticated, the Xbox token acquired, and a purchase completed, you are ready to call the [RedeemMicrosoftStoreInventoryItems](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) API. + +Include the `EntityToken` as the `X-EntityToken` header, and provide the Xbox token in the request body: + +```json +{ + "XboxToken": "{Your Xbox token from GetTokenAndSignatureAsync}" +} +``` + +### How redemption works + +When the `RedeemMicrosoftStoreInventoryItems` call is made, PlayFab uses the Xbox token to query the Microsoft Store Collections API for any unredeemed purchases associated with the player's account. It then matches those purchases against the **Store IDs** configured in your PlayFab Bundle Marketplace Mappings and grants the corresponding items. + +A successful response includes a `200` status code alongside the [RedeemMicrosoftStoreInventoryItemsResponse](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items), which contains: + +- **Succeeded**—A list of successfully redeemed items. +- **Failed**—A list of items that failed to redeem. +- **TransactionIds**—IDs for each redemption transaction. + +Each redemption action triggers a corresponding event in the player's transaction history, which can be retrieved from the **Transaction History (V2)** tab under the player's overview page in [Game Manager](https://developer.playfab.com/). + +Alongside the record in the player's transaction history, an `items_redeemed` **PlayStream** event is also triggered and logged. You can access these logs for your Title by going to the **Data** page under the **Analyze** section of the left navigation bar in [Game Manager](https://developer.playfab.com/). + +### Fulfillment for Developer-managed consumables + +If the redeemed product is a **Developer-managed consumable**, PlayFab automatically reports it as **fulfilled** (consumed) with the Microsoft Store on your behalf after a successful redemption. The fulfillment step is necessary before the player can repurchase the same consumable. If the consumable does not appear as fulfilled after a successful redemption, retry the `RedeemMicrosoftStoreInventoryItems` call. If the issue persists, escalate to the PlayFab team through your support channel. Durables do not require fulfillment because they are one-time purchases. For more information, see [Managing consumables and refunds](/gaming/gdk/docs/store/commerce/service-to-service/xstore-managing-consumables-and-refunds). + +## Troubleshooting + +If the redemption call returns `200` but all three arrays (`Succeeded`, `Failed`, `TransactionIds`) are empty, the Microsoft Store Collections API is not finding any matching items. This result typically indicates a configuration issue. See the [troubleshooting section](../marketplace-integrations/microsoft.md#troubleshooting) in the Microsoft Store integration guide for a full list of common causes and resolutions. + +If the API returns an HTTP error (such as 400), check the error response for codes like `InvalidCatalogItemConfiguration`, `InvalidXboxLiveToken`, or `AccountNotLinked`. + +## See also + +- [Microsoft Store marketplace integration](../marketplace-integrations/microsoft.md) +- [RedeemMicrosoftStoreInventoryItems API reference](/rest/api/playfab/economy/inventory/redeem-microsoft-store-inventory-items) +- [Fraud prevention quickstart](/gaming/playfab/economy-monetization/economy-v2/fraud-prevention/quickstart) +- [Xbox Live add-on configuration](/gaming/playfab/identity/player-identity/platform-specific-authentication/xbox-live-add-on) +- [How to successfully integrate an Apple app into Game Manager](../marketplace-integrations/apple.md) +- [How to successfully integrate a Google app into Game Manager](../marketplace-integrations/google.md) diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/overview.md b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/overview.md index a6a050ca9..f7742ed2f 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/overview.md +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/overview.md @@ -18,25 +18,29 @@ After a successful marketplace integration, the next step is to focus on redeemi ### Apple -Redemption from the Apple marketplace involves verifying the purchase receipt with Apple's servers and updating the player's inventory or account accordingly. For more details see [Apple redemption documentation](apple.md) +Redemption from the Apple marketplace involves verifying the purchase receipt with Apple's servers and updating the player's inventory or account accordingly. For more information, see [Apple redemption documentation](apple.md). ### Google -Redemption from the Google marketplace involves verifying the purchase receipt with Google's servers and updating the player's inventory or account accordingly. For more details see [Google redemption documentation](google.md) +Redemption from the Google marketplace involves verifying the purchase receipt with Google's servers and updating the player's inventory or account accordingly. For more information, see [Google redemption documentation](google.md). + +### Microsoft Store + +Redemption from the Microsoft Store involves using an Xbox token to query the Microsoft Store Collections API for unredeemed purchases and granting the corresponding items to the player's inventory. For more information, see [Microsoft Store redemption documentation](microsoft.md). ### Steam -Redemption from the Steam marketplace involves verifying the purchase receipt with Steam's servers and updating the player's inventory accordingly. For more details see [Steam redemption documentation](steam.md) +Redemption from the Steam marketplace involves verifying the purchase receipt with Steam's servers and updating the player's inventory accordingly. For more information, see [Steam redemption documentation](steam.md). ## Subscription Redemption ### Apple Subscriptions -Subscription redemption from the Apple marketplace involves verifying the subscription receipt with Apple's servers and updating the player's account accordingly. For more details see [Apple subscription documentation](ios-subscription-redemption.md). +Subscription redemption from the Apple marketplace involves verifying the subscription receipt with Apple's servers and updating the player's account accordingly. For more information, see [Apple subscription documentation](ios-subscription-redemption.md). ### Google Subscriptions -Subscription redemption from the Google marketplace involves verifying the subscription receipt with Google's servers and updating the player's account accordingly. For more details see [Google subscription documentation](google-subscription-redemption.md). +Subscription redemption from the Google marketplace involves verifying the subscription receipt with Google's servers and updating the player's account accordingly. For more information, see [Google subscription documentation](google-subscription-redemption.md). ## Conclusion diff --git a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/toc.yml b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/toc.yml index 94c081921..615836729 100644 --- a/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/toc.yml +++ b/playfab-docs/economy-monetization/economy-v2/marketplace/marketplace-redemption/toc.yml @@ -3,6 +3,8 @@ items: href: overview.md - name: Google redemption href: google.md + - name: Microsoft Store redemption + href: microsoft.md - name: Steam redemption href: steam.md - name: Google subscription redemption diff --git a/playfab-docs/economy-monetization/economy-v2/quickstart.md b/playfab-docs/economy-monetization/economy-v2/quickstart.md index 6750d7489..17e9a3c0a 100644 --- a/playfab-docs/economy-monetization/economy-v2/quickstart.md +++ b/playfab-docs/economy-monetization/economy-v2/quickstart.md @@ -197,7 +197,7 @@ Fill in the required metadata – there are only four required properties (_Crea Create a "Draft" Catalog Item by calling the [CreateDraftItem](/rest/api/playfab/economy/catalog/create-draft-item) endpoint: * The EntityToken (from GetEntityToken or other PlayFab `login` call) in the X-EntityToken header -* The Playfab Title ID in the item's CreatorEntity.Id +* The PlayFab Title ID in the item's CreatorEntity.Id ```bash curl \ @@ -355,7 +355,7 @@ Create a Draft Currency Catalog Item by calling the [CreateDraftItem](/rest/api/ * An EntityToken with Catalog Permissions * The Entity.Id as the item 'Creator' -* The Playfab Title ID +* The PlayFab Title ID * The Item should be a Bundle of type 'Currency' and contain a Title and Description Call PublishItem with the ItemId returned from the CreateDraftItem. diff --git a/playfab-docs/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment.md b/playfab-docs/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment.md index 91dde9d3c..f9a4fc398 100644 --- a/playfab-docs/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment.md +++ b/playfab-docs/economy-monetization/economy-v2/tutorials/craftingGame/crafting-game-environment.md @@ -51,6 +51,6 @@ If you followed the steps so far, the package manager should now be open in VS. Once you have the appropriate source added to the package manager, you should now be able to search for the PlayFab SDK, called **PlayFabAllSDK**. This search should return some available packages, the one you're looking for shares the exact name mentioned previously, and looks like this: -![Playfab SDK](../../media/crafting-game-images/pf-sdk.png) +![PlayFab SDK](../../media/crafting-game-images/pf-sdk.png) Once installed you can start using all of the PlayFab API functions! We can now move on to the next step. diff --git a/playfab-docs/economy-monetization/economy-v2/ugc/index.yml b/playfab-docs/economy-monetization/economy-v2/ugc/index.yml index 830c6b87c..531c154c2 100644 --- a/playfab-docs/economy-monetization/economy-v2/ugc/index.yml +++ b/playfab-docs/economy-monetization/economy-v2/ugc/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab UGC documentation # < 60 chars +title: PlayFab UGC documentation # < 60 chars summary: summary # < 160 chars metadata: diff --git a/playfab-docs/economy-monetization/economy/index.yml b/playfab-docs/economy-monetization/economy/index.yml index 89816056c..4b697db84 100644 --- a/playfab-docs/economy-monetization/economy/index.yml +++ b/playfab-docs/economy-monetization/economy/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Economy documentation # < 60 chars +title: PlayFab Economy documentation # < 60 chars summary: PlayFab Economy provides you with the necessary features to more deeply engage with your community and monetize your game. # < 160 chars metadata: diff --git a/playfab-docs/economy-monetization/index.yml b/playfab-docs/economy-monetization/index.yml index 04d08668e..81d801050 100644 --- a/playfab-docs/economy-monetization/index.yml +++ b/playfab-docs/economy-monetization/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Economy v2 documentation # < 60 chars +title: PlayFab Economy v2 documentation # < 60 chars summary: PlayFab Economy v2 provides a platform to build and grow marketplaces, progression, and engagement that scale with your players. # < 160 chars metadata: diff --git a/playfab-docs/get-started/index.yml b/playfab-docs/get-started/index.yml index f4bd6f9f4..4315f0c7b 100644 --- a/playfab-docs/get-started/index.yml +++ b/playfab-docs/get-started/index.yml @@ -1,11 +1,11 @@ ### YamlMime:Landing -title: Azure PlayFab fundamentals -summary: From pre-production to post-launch, learn how PlayFab can help you build and operate your game. # < 160 chars +title: PlayFab fundamentals +summary: From preproduction to post-launch, learn how PlayFab can help you build and operate your game. # < 160 chars metadata: - title: Azure PlayFab fundamentals and getting started documentation - description: From pre-production to post-launch, learn how PlayFab can help you build and operate your game. # Required; article description that is displayed in search results. < 160 chars. + title: PlayFab fundamentals and getting started documentation + description: From preproduction to post-launch, learn how PlayFab can help you build and operate your game. # Required; article description that is displayed in search results. < 160 chars. ms.service: azure-playfab #Required; service per approved list. service slug assigned to your service by ACOM. ms.topic: landing-page author: m-kdearnley @@ -22,7 +22,7 @@ landingContent: linkLists: - linkListType: overview links: - - text: What is Playfab? + - text: What is PlayFab? url: what-is-playfab.md - linkListType: concept links: diff --git a/playfab-docs/get-started/what-is-playfab.md b/playfab-docs/get-started/what-is-playfab.md index 8ee3193d7..8ec6b1d4e 100644 --- a/playfab-docs/get-started/what-is-playfab.md +++ b/playfab-docs/get-started/what-is-playfab.md @@ -10,11 +10,11 @@ keywords: playfab, analytics, multiplayer, authentication, leaderboards, liveops ms.localizationpriority: medium --- -# What is Azure PlayFab? +# What is PlayFab? -Azure PlayFab is a complete backend platform for games, featuring managed game services, real-time analytics, and live operations management capabilities. These features help you engage and retain players, monetize your experiences, collect and analyze game data, and build player experiences across gaming platforms and devices. +PlayFab is a complete backend platform for games, featuring managed game services, real-time analytics, and live operations management capabilities. These features help you engage and retain players, monetize your experiences, collect and analyze game data, and build player experiences across gaming platforms and devices. -PlayFab's cost-effective and highly-scalable solutions are backed by the world-class infrastructure and a global reach of Azure, allowing all game creators to build and launch their games with confidence. Whether you are a team of one or one thousand, PlayFab has solutions that scale for all sizes of game. PlayFab is the perfect complement to your game: choose which PlayFab features you want to use, extend PlayFab capabilities with cloud-based logic, or connect PlayFab with your own bespoke game services. +PlayFab's cost-effective and highly-scalable solutions are backed by the world-class infrastructure and a global reach of Azure, allowing all game creators to build and launch their games with confidence. Whether you're a team of one or one thousand, PlayFab has solutions that scale for all sizes of game. PlayFab is the perfect complement to your game: choose which PlayFab features you want to use, extend PlayFab capabilities with cloud-based logic, or connect PlayFab with your own bespoke game services. By managing the essential backend components, PlayFab can help you and your team devote more time to innovating and perfecting the elements of your game that matter most. @@ -38,11 +38,11 @@ PlayFab provides the following services: ## Cross-network identity -**Player authentication**: Start with frictionless authentication and let players link accounts to roam across Windows, Xbox, Steam, PlayStation™Network, Nintendo, Facebook, iOS, Android, and more. +**Player authentication**: Start with frictionless authentication and let players link accounts to roam across Windows, Xbox, Steam, PlayStation™ Network, Nintendo, Facebook, iOS, Android, and more. ## Live service management -**Game Manager web portal**: A shared space (with roles and access permissions) where studio members can build, configure and operate your game. +**Game Manager web portal**: A shared space (with roles and access permissions) where studio members can build, configure, and operate your game. **Title data**: Manage your game configuration remotely. @@ -90,7 +90,7 @@ PlayFab provides the following services: ## Community -**Leaderboards**: Facilitate permanent or time-limited competitions amongst friends or strangers. +**Leaderboards**: Facilitate permanent or time-limited competitions among friends or strangers. ### Chat diff --git a/playfab-docs/identity/index.yml b/playfab-docs/identity/index.yml index 9f390886d..91de3995f 100644 --- a/playfab-docs/identity/index.yml +++ b/playfab-docs/identity/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Identity documentation +title: PlayFab Identity documentation summary: Overviews, quickstarts, and tutorials that provide guidance on player login and GameManager authentication. # < 160 chars metadata: diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md b/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md index 7d5b168c7..00c164c80 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/anonymous-login.md @@ -10,7 +10,7 @@ keywords: playfab, authentication, server, anonymous login, customid ms.localizationpriority: medium --- -# Setting up Playfab Authentication using Anonymous Login +# Setting up PlayFab Authentication using Anonymous Login This guide shows you how to implement PlayFab authentication using anonymous login APIs with server-side protection, focusing only on CustomID authentication using HTML5/JavaScript. @@ -26,7 +26,7 @@ To enhance the security of anonymous login, PlayFab implemented a crucial securi - Disabling client-side player creation prevents unauthorized account creation directly from unauthorized clients. - Only existing players can log in through client-side APIs. -2. **Enabled Server-Side Player Creation**: +1. **Enabled server-side player creation**: - Player account creation is now handled through server-side APIs (`LoginWithCustomID`, `LoginWithAndroidDeviceID`, `LoginWithIOSDeviceID`, `LoginWithNintendoDeviceId`). - This ensures all account creation happens in a secure, controlled environment. @@ -41,9 +41,9 @@ To enhance the security of anonymous login, PlayFab implemented a crucial securi > [!NOTE] > If you need help with setting up a server, see the [Running an HTTP server for testing](running-an-http-server-for-testing.md) tutorial. Throughout this guide, we'll assume your domain is `http://playfab.example`. -## Authentication Flow +## Authentication flow -1. **Server-side Account Creation**: +1. **Server-side account creation**: - Use `Server/LoginWithCustomID` with the server API to create new players - Requires a title secret key - Reference: [Server API - Login With Custom ID](xref:titleid.playfabapi.com.server.authentication.loginwithcustomid) @@ -52,9 +52,9 @@ To enhance the security of anonymous login, PlayFab implemented a crucial securi - Use `Client/LoginWithCustomID` with the client API to log in existing players - Reference: [Client API - Login With Custom ID](xref:titleid.playfabapi.com.client.authentication.loginwithcustomid) -## Implementation Steps +## Implementation steps -### 1. Set Up Your Development Environment +### 1. Set up your development environment 1. Download the JavaScript SDK from the [JavaScript SDK documentation](https://learn.microsoft.com/gaming/playfab/sdks/javascript/) 2. Install the required Node.js packages: @@ -63,7 +63,7 @@ To enhance the security of anonymous login, PlayFab implemented a crucial securi npm install playfab-sdk ``` -### 2. Server-Side Implementation (Node.js) +### 2. Server-side implementation (Node.js) > [!IMPORTANT] > Keep your title secret key secure and never expose it in client-side code. The secret key should only be used in secure server environments. @@ -121,7 +121,7 @@ server.listen(port, () => { }); ``` -### 3. Client-Side Implementation (HTML) +### 3. Client-side implementation (HTML) ```html @@ -160,18 +160,18 @@ server.listen(port, () => { ``` -## Configuring Player Creation Settings +## Configuring player creation settings -### For Existing Titles +### For existing titles 1. Navigate to the PlayFab developer portal and select your title -2. Go to **Settings** -3. Select the **API Features** tab +1. Go to **Settings**. +1. Select the **API Features** tab. 4. Check the box to prevent new player accounts from being created via anonymous login APIs ![Disabling player creation using Client/LoginWithCustomId](media/tutorials/anonymous-html5/existing_title.png) -### For New Titles +### For new titles > [!WARNING] > Enabling automatic player creation for anonymous login APIs can compromise security. Only enable this feature temporarily during development or testing. Always disable it before moving to production. @@ -179,16 +179,16 @@ server.listen(port, () => { New titles have player creation via anonymous APIs disabled by default. To enable for testing, perform the following: 1. Navigate to the PlayFab developer portal and select your title -2. Go to **Settings** -3. Select the **API Features** tab +1. Go to **Settings**. +1. Select the **API Features** tab. 4. Uncheck the box to allow new player accounts from being created via anonymous login APIs ![Enabling player creation using Client/LoginWithCustomId](media/tutorials/anonymous-html5/new_title.png) -## Testing and Response Examples +## Testing and response examples -### Server Response Example +### Server response example When successfully creating a user through the server API, you receive a response similar to: @@ -204,7 +204,7 @@ When successfully creating a user through the server API, you receive a response } ``` -### Client Response Example +### Client response example When attempting to create a new account from the client API (which is now disabled), you receive an error: @@ -229,7 +229,7 @@ When successfully logging in an existing user through the client API: } } ``` -## Further Reading +## Further reading - [PlayFab Authentication Overview](../authentication/index.md) - [Login Basics and Best Practices](../login/login-basics-best-practices.md) diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/kongregate-html5.md b/playfab-docs/identity/player-identity/platform-specific-authentication/kongregate-html5.md index b87e45e9b..6b32dc530 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/kongregate-html5.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/kongregate-html5.md @@ -40,11 +40,11 @@ To do this, we need to prepare an `index.html` file with the following content. Navigate to the [Kongregate website](https://www.kongregate.com/): 1. Select the **Games** tab. -2. Then select the **Upload your game** button. +1. Select the **Upload your game** button. ![Kongregate Games tab](media/tutorials/kongregate-games-tab.png) -A page to set up for a new application will open. +A page to set up for a new application opens. 1. Enter the **Application Name** in the **Title** field. 2. Then enter a **Game Description** in the field provided. @@ -53,9 +53,9 @@ A page to set up for a new application will open. ![Kongregate upload your game](media/tutorials/kongregate-upload-your-game.png) -You will be moved to the **Application Upload** page. +You'll be moved to the **Application Upload** page. -As a *very* important first step, make sure to save the **URL** from your **Web Address Bar**. This will save you a lot of time trying to restore access to the application once you close the page. +As an important first step, make sure to save the **URL** from your **Web Address Bar**. This saves you a lot of time trying to restore access to the application once you close the page. 1. Once this is done, select the prepared **index.html** file as your **Game File**. 2. Then set up the screen size. @@ -78,14 +78,14 @@ As a *very* important first step, make sure to save the **URL** from your **Web In your PlayFab title Game Manager: 1. Navigate to **Add-ons**. -2. Then locate and select **Kongregate**, as shown in the example provided below. +1. Find and select **Kongregate**. ![PlayFab select Kongregate Add-on](media/tutorials/playfab-select-kongregate-add-on.png) -A new page will open, allowing you to set up **Kongregate** integration. +A new page opens, allowing you to set up **Kongregate** integration. 1. Enter the **API Key** you acquired in the previous section. -2. Select the **Install Kongregate** button. +1. Select **Install Kongregate**. ![PlayFab set up Kongregate integration](media/tutorials/playfab-set-up-kongregate-integration.png) @@ -145,7 +145,7 @@ Use the example code shown below to populate the `index.html` for your game. // The function prepares and triggers PlayFab LoginWithKongregate API call function loginInUsingPlayFab() { - // Setting up playfab title ID + // Setting up PlayFab title ID PlayFab.settings.titleId = "159F"; // forming request @@ -184,7 +184,7 @@ Use the example code shown below to populate the `index.html` for your game. ## Testing -Remember that URL we asked you to save in a safe and accessible place a little earlier? Use it now to access your **Application Upload** page. +Remember that URL we asked you to save in a safe and accessible place a little earlier? Use it now to access your **Application Upload** page. 1. Select **index.html** as your **Game File**. 2. Set up the screen size. @@ -197,6 +197,6 @@ Once the preview loads, wait for the Application to obtain the **Kongregate User - When that has happened, select the **PlayFab Login With Kongregate** button. - After a brief pause, you should receive an **Authenticated via PlayFab** message. -- At this point you have successfully logged in using PlayFab and Kongregate! +- At this point, you have successfully logged in using PlayFab and Kongregate! ![Testing PlayFab Login with Kongregate](media/tutorials/kongregate-html5/testing-playfab-login-with-kongregate.png) diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml b/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml index d5c88b4e4..7e3d2e2dd 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/toc.yml @@ -37,5 +37,5 @@ href: xbox-live-add-on.md - name: Integrating the Universal Windows Platform with PlayFab href: uwp-integration.md - - name: Setting up Playfab Authentication using Anonymous Login + - name: Setting up PlayFab Authentication using Anonymous Login href: anonymous-login.md diff --git a/playfab-docs/index.yml b/playfab-docs/index.yml index ba4411f27..2bd5df06c 100644 --- a/playfab-docs/index.yml +++ b/playfab-docs/index.yml @@ -1,12 +1,12 @@ ### YamlMime:Hub # root section (required) -title: Azure PlayFab documentation -summary: Learn how to build and manage engaging games using Microsoft Azure PlayFab services. -# brand: playfab +title: PlayFab documentation +summary: Learn how to build and manage engaging games using Microsoft PlayFab services. +# brand: PlayFab metadata: - title: Azure PlayFab documentation + title: PlayFab documentation description: PlayFab is a complete backend platform for live games. services: service ms.service: azure-playfab diff --git a/playfab-docs/live-service-management/gamemanager/reference.md b/playfab-docs/live-service-management/gamemanager/reference.md index 60e1ecf70..afe986e05 100644 --- a/playfab-docs/live-service-management/gamemanager/reference.md +++ b/playfab-docs/live-service-management/gamemanager/reference.md @@ -12,9 +12,9 @@ ms.localizationpriority: medium # Game Manager reference -This reference familiarizes you with the high-level aspects of the Game Manager. For more detailed information, you may select your specific topic of interest in the PlayFab documentation that follows. +This reference familiarizes you with the high-level aspects of the Game Manager. For more detailed information, select your specific article of interest in the PlayFab documentation that follows. -To get the most value from this topic, you should have created your PlayFab account, logged in, and viewed the Game Manager for your title, even if it's an empty title for now. +To get the most value from this article, you should create your PlayFab account, logged in, and viewed the Game Manager for your title, even if it's an empty title for now. The sections provided below offer greater insight on each Game Manager area. Each time you perform an API call or task, view the results in the Game Manager in the appropriate area for that task. @@ -29,24 +29,24 @@ Game Manager is split into four major sections: - Engage – Facilitate connections with players. - Analyze – Monitor and act on player behaviors. -## Title Overview +## Title overview An overview of the recent and less-recent performance of your title. -**Overview** - shows your game's basic statistics and what you may have assigned as Key Performance Indicators (KPIs). In the upper-right, you will find time period toggle buttons, and there are also filters for the tables. +**Overview** - shows your game's basic statistics and what you assigned as Key Performance Indicators (KPIs). In the upper-right, you'll find time period toggle buttons. There are also filters for the tables. -- **4h**: This will load data generated within the last 4 hours. -- **24h**: This will load data generated within the last 24 hours. -- **3d**: This will load data generated within the last 3 days. -- **7d**: This will load data generated within the last 7 days. -- **mtd**: This will load data generated within the current month. +- **4h**: This loads data generated within the last 4 hours. +- **24h**: This loads data generated within the last 24 hours. +- **3d**: This loads data generated within the last three days. +- **7d**: This loads data generated within the last seven days. +- **mtd**: This loads data generated within the current month. > [!NOTE] > In Game Manager, all times are displayed in local time. ![Game Manager - Dashboards](media/tutorials/game-manager-dashboard.png) -The tables in the Overview tab allow you to monitor PlayStream events in real time. They include the following: +The tables in the Overview tab allow you to monitor PlayStream events in real time. They include the following metrics: - **Unique Users**: The average number of unique players logging in per day. - **API Calls**: Indicates how many API calls were executed within the given time period. @@ -70,7 +70,7 @@ In this section of the Game Manager, a sorted list is presented, and organized b ![Game Manager - Players Tab](media/tutorials/game-manager-players-tab.png) -**Overview** - this detailed screen provides a wealth of insight into the players' activities. The sub-menu contains many links to other player-centric information, as shown below. +**Overview** - this detailed screen provides a wealth of insight into the players' activities. The submenu contains many links to other player-centric information, as shown below. ![Game Manager - Player - Overview](media/tutorials/game-manager-player-overview.png) @@ -92,9 +92,9 @@ Some specific tools your team can use to remedy defrauded players and identify p Multiplayer allows you to configure server hosting and matchmaking. -**Servers** - Whether you are looking to hosting multi-player matches or just need a secure environment that can reduce many common forms of hacking and abuse, the PlayFab Thunderhead servers work with many architectures and game types. These servers provide an excellent alternative when compared with the overhead of dedicated game servers. +**Servers** - Whether you're looking to hosting multi-player matches or just need a secure environment that can reduce many common forms of hacking and abuse, the PlayFab Thunderhead servers work with many architectures and game types. These servers provide an excellent alternative when compared with the overhead of dedicated game servers. -**Matchmaking** - Set up your matchmaking queues by configuring match sizes, servers and statistics. +**Matchmaking** - Set up your matchmaking queues by configuring match sizes, servers, and statistics. ![Matchmaking](media/tutorials/game-manager-multiplayer-matchmaking.png) @@ -129,7 +129,7 @@ To configure marketplace integrations for your title: Explore the **Add-ons** se ![Game Manager - Add-ons - Partner Add-ons](media/tutorials/game-manager-add-ons-partner-add-ons.png) -Setup instructions for each add-on may vary. Additional billing information may also be required. +Setup instructions for each add-on vary. More billing information might also be required. [Back to About the Game Manager](#about-game-manager) @@ -149,7 +149,7 @@ As an example, the following image shows the primary catalogs for **Unicorn Batt **Items** - An item within the catalog. Items can be of several different types. -**Stores**- A subset of catalog items that can be set to prices that are different than those specified by the catalog. +**Stores**- A subset of catalog items that can be set to prices that are different than prices specified by the catalog. ![Game Manager - Economy - Catalogs - Edit Container](media/tutorials/game-manager-economy-catalogs-edit-container.png) @@ -171,7 +171,7 @@ Additional Information: ### User Generated Content -The User Generated Content tab displays all published content for your title. When enabled, all users can create, discover, and consume content. +The **User Generated Content** (UGC) tab displays all published content for your title. When enabled, all users can create, discover, and consume content. ![UGC Landing Page](media/tutorials/game-manager-ugc.png) @@ -196,15 +196,15 @@ Additional Information: ### Progression -The Progression tab displays all the active stats and leaderboards for your title. [Playfab Statistics](../../player-progression/statistics/index.md) and [PlayFab Leaderboards](../../community/leaderboards/quickstart-leaderboards.md) can be defined and configured here. You can even link a leaderboard to a stat to have one call drive updates for both. +The Progression tab displays all the active stats and leaderboards for your title. [PlayFab Statistics](../../player-progression/statistics/index.md) and [PlayFab Leaderboards](../../community/leaderboards/quickstart-leaderboards.md) can be defined and configured here. You can even link a leaderboard to a stat to have one call drive updates for both. - [Back to About the Game Manager](#about-game-manager) ### Content -The Content section offers tools for engaging with your players. The content can include news, remote configuration, and files. +The Content section offers tools for engaging with your players. The content can include news, remote configuration, and files. -**Title Data** - Here you can configure and store key properties which you can change after your game launches. Title data is accessible from all API sets by all users. Because of this, title data is an ideal place to store your custom title settings. Internal data is hidden from game clients and only available on your game servers. +**Title Data** - Here you can configure and store key properties that you can change after your game launches. Title data is accessible from all API sets by all users. Because of this, title data is an ideal place to store your custom title settings. Internal data is hidden from game clients and only available on your game servers. ### Add or edit title data keys @@ -222,11 +222,11 @@ The Content section offers tools for engaging with your players. The content ca **Title News** - Create title news for your game title. As needed, add additional languages. -**File Management** - Create, organize and upload files for your game client via the Content Delivery Network (CDN). +**File Management** - Create, organize, and upload files for your game client via the Content Delivery Network (CDN). > [!NOTE] > There are varying time delays, depending on the type of file handling that is required. For detailed information, view the online Help for the File Management tab. -**Email Templates** - Create, configure and manage email templates for game clients. +**Email Templates** - Create, configure, and manage email templates for game clients. The following example shows the **Email Templates** tab for *Great Game*. @@ -242,11 +242,11 @@ Analyze allows you to monitor and act on player behaviors. ### Dashboards -Dashboards allow you to see Trends, run Reports and perform Diagnostics. +Dashboards allow you to see Trends, run Reports, and perform Diagnostics. ### Data -In the **Data** area you can do a number of things to track and analyze data from your players' activities. There are a number of graphing and reports capabilities that provide the ability to consolidate and visualize the data. +In the **Data** area, you can do many things to track and analyze data from your players' activities. There are a number of graphing and reports capabilities that provide the ability to consolidate and visualize the data. **Trends** - Configure and view trends for a number of statistics for time periods ranging from 7 days to 26 months. The Trends graph shows classic retention - only new players that have returned - for the chosen time period. The 30-day retention report includes both new and returning players. **Event History** - Search and display a number of different Event History types, depending on the query you create. Use event name, date range, or event values. @@ -254,7 +254,7 @@ In the **Data** area you can do a number of things to track and analyze data fro ![Game Manager - Reports](media/tutorials/game-manager-analytics-reports.png) -For additional or custom reports, please open a feature request in our [community forums](https://community.playfab.com/spaces/24/index.html). +For additional or custom reports, open a feature request in our [community forums](https://community.playfab.com/spaces/24/index.html). **Webhooks** - Webhooks allow you to have some or all of your PlayStream events forwarded to any web URL you want. The event data is sent via POST in the request body as JSON. @@ -281,7 +281,7 @@ On the Audit History page, select any entry in the log to view the complete deta Access the title settings from the Settings menu. -**General** - Provides basic information that you will use to configure your title such as player display names and the default language for your title. +**General** - Provides basic information that you'll use to configure your title such as player display names and the default language for your title. ![Game Manager - Settings - General Tab](media/tutorials/game-manager-settings-general.png) @@ -294,12 +294,12 @@ Choose your preferred options, and select the **Save** button. **Secret Keys** - Allows you to create and manage your PlayFab secret keys, the unique identifier for your game when making Admin and server API calls. > [!IMPORTANT] -> This key should only be shared with trusted members of your development team, since it enables API calls that can affect game data and player accounts. Never share your PlayFab API secret key with anyone; doing so may jeopardize your title's security. +> This key should only be shared with trusted members of your development team, since it enables API calls that can affect game data and player accounts. Never share your PlayFab API secret key with anyone; doing so might jeopardize your title's security. **Email Preferences** - Allows you to configure e-mail settings such as Subscription and Reply-To addresses. **Push Notifications** - Configure notifications to be sent to android or iOS devices. **Limits** - Set limits on certain PlayFab features, economic or otherwise in your game. -**Client Profile Options** - Allows you to configure what a Client can or cannot access and configure on their own for the title. +**Client Profile Options** - Allows you to configure what a Client can or can't access and configure on their own for the title. ## Other basic actions @@ -316,7 +316,7 @@ Choose your preferred options, and select the **Save** button. ### View PlayFab news -New notifications will be indicated in the little bell icon in the upper-right corner of your window. +New notifications are indicated in the little bell icon in the upper-right corner of your window. 1. Select icon to display **News**. 2. View the news from the PlayFab team, ordered by the most recent, first. The news feeds include information on new features, API updates, and service outages. @@ -325,18 +325,18 @@ New notifications will be indicated in the little bell icon in the upper-right c ### Create and edit studios and titles -In this section you learn how to create and manage studios and game titles. +In this section, you learn how to create and manage studios and game titles. **To add a new studio:** -1. Click the PlayFab icon to display the **My Studios** and **Titles** pages. -2. Click **NEW STUDIO** to create a new studio in the dialog that appears. +1. Select the PlayFab icon to display the **My Studios** and **Titles** pages. +2. Select **NEW STUDIO** to create a new studio in the dialog that appears. 3. Enter a **Studio Name** and **Authentication provider**. 4. Save your changes and return to the My Studios and Titles page. **To edit an existing studio:** -1. Select the elipsis drop-down menu to the right side of your **Studio name**, then select **Studio settings**. +1. Select the ellipsis drop-down menu to the right side of your **Studio name**, then select **Studio settings**. ![Game manager - Edit Studio](media/tutorials/game-manager-mystudiosandtitles-settings.png) 2. Make your edits. @@ -345,7 +345,7 @@ In this section you learn how to create and manage studios and game titles. **To add a new title:** 1. Select the drop-down menu to the right side of your Studio's Name, and then select **New title** to display the Create Title page. -2. Enter the details and click the **CREATE TITLE** button. +2. Enter the details and select the **CREATE TITLE** button. ![Game manager - Create a new game](media/tutorials/game-manager-create-title.png) 3. Save your changes and return to the My Studios and Titles page. @@ -360,12 +360,12 @@ In this section you learn how to create and manage studios and game titles. ### About User Accounts -You can create user accounts that are individual or Admin-level accounts. Admin accounts provide access to one or more sections on one or more titles of a given studio, and of course provide full ability to configure studio and title information. +You can create user accounts that are individual or Admin-level accounts. Admin accounts provide access to one or more sections on one or more titles of a given studio, and provide full ability to configure studio and title information. ![Game manager - Studio Users](media/tutorials/game-manager-studio-users.png) 1. Select the drop-down menu to the far right from your Studio name, and then select **Studio users**. 2. Choose **ADD USER** to display the Add New User page. Check the box if you want to make the user an Admin. -3. To remove accounts in the **Users** page, simply select **Remove**. +3. To remove accounts in the **Users** page, select **Remove**. -If you do not already have a PlayFab Admin account, an e-mail will be sent to the address you provided. Upon confirmation, the new account will have access to the Studio and title. +If you don't already have a PlayFab Admin account, an e-mail is sent to the address you provided. Upon confirmation, the new account has access to the Studio and title. diff --git a/playfab-docs/live-service-management/index.yml b/playfab-docs/live-service-management/index.yml index c2ea92f22..02960eef0 100644 --- a/playfab-docs/live-service-management/index.yml +++ b/playfab-docs/live-service-management/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Live service management documentation +title: PlayFab Live service management documentation summary: Manage and optimize your game effectively with game configuration and title data, player segmentation for targeted configuration and AB testing, and title-wide communication tools. # < 160 chars metadata: diff --git a/playfab-docs/multiplayer/index.yml b/playfab-docs/multiplayer/index.yml index b7a6b9826..c423a889c 100644 --- a/playfab-docs/multiplayer/index.yml +++ b/playfab-docs/multiplayer/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Multiplayer documentation +title: PlayFab Multiplayer documentation summary: PlayFab Multiplayer services support real-time multiplayer capabilities for matchmaking, grouping, networking, and server hosting. # < 160 chars metadata: diff --git a/playfab-docs/multiplayer/lobby/create-a-lobby.md b/playfab-docs/multiplayer/lobby/create-a-lobby.md index bb523de61..66c0e8ad2 100644 --- a/playfab-docs/multiplayer/lobby/create-a-lobby.md +++ b/playfab-docs/multiplayer/lobby/create-a-lobby.md @@ -24,7 +24,7 @@ There are several ways a lobby can be created. From a technical perspective, all lobbies are fall into two main categories based on ownership—server-owned and client-owned. To learn more, see [Owner requirements and privileges](owner-requirements-and-privileges.md). -The general usage of PlayFab Lobby is to temporarily hold a group of players together. For commonly used applications of Lobby, see the [Azure PlayFab Lobby overview](index.md). +The general usage of PlayFab Lobby is to temporarily hold a group of players together. For commonly used applications of Lobby, see the [PlayFab Lobby overview](index.md). ### Supported entity types diff --git a/playfab-docs/multiplayer/lobby/index.md b/playfab-docs/multiplayer/lobby/index.md index d7f2cbb4b..5892e9f89 100644 --- a/playfab-docs/multiplayer/lobby/index.md +++ b/playfab-docs/multiplayer/lobby/index.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Lobby overview +title: PlayFab Lobby overview author: joannaleecy -description: Learn about Azure PlayFab Lobby. +description: Learn about PlayFab Lobby. ms.author: jenelleb ms.date: 04/08/2025 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, lobby, matchmaking ms.localizationpriority: medium --- -# Azure PlayFab Lobby overview +# PlayFab Lobby overview -Azure PlayFab Lobby is a service to create a temporary grouping mechanism for players to play games together. It's frequently used together with matchmaking, allowing for pre-formed groups to join the same matchmaking ticket, or allowing matched players to convene and receive further notifications about the group such as join/leave events or server connection details. +PlayFab Lobby is a service to create a temporary grouping mechanism for players to play games together. It's frequently used together with matchmaking, allowing for pre-formed groups to join the same matchmaking ticket, or allowing matched players to convene and receive further notifications about the group such as join/leave events or server connection details. ## Benefits diff --git a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md index 5ed1b9db7..80ffe2473 100644 --- a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md +++ b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md @@ -14,7 +14,7 @@ ms.date: 03/14/2022 The Matchmaking and Lobby features have built in support for real-time notifications. Notifying players of changes to Matchmaking or Lobby has never -been easier, as the work to handle notifications is done for you in the [Azure PlayFab Lobby and Matchmaking SDK](lobby-matchmaking-sdks/lobby-matchmaking-sdks.md). New APIs will +been easier, as the work to handle notifications is done for you in the [PlayFab Lobby and Matchmaking SDK](lobby-matchmaking-sdks/lobby-matchmaking-sdks.md). New APIs will allow connected clients to subscribe for notifications of Lobby and Matchmaking changes. With this addition, you'll no longer need to poll for changes to matches or lobbies. diff --git a/playfab-docs/multiplayer/lobby/lobby-getting-started.md b/playfab-docs/multiplayer/lobby/lobby-getting-started.md index 7a1b739c0..04e3dbfef 100644 --- a/playfab-docs/multiplayer/lobby/lobby-getting-started.md +++ b/playfab-docs/multiplayer/lobby/lobby-getting-started.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Lobby SDK Quickstart -This article describes how to set up the development environment for Azure PlayFab Lobby and create your first lobby using the PlayFab Multiplayer C/C++ SDK. +This article describes how to set up the development environment for PlayFab Lobby and create your first lobby using the PlayFab Multiplayer C/C++ SDK. > [!NOTE] > The PlayFab Multiplayer SDK also provides APIs for PlayFab Matchmaking. diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md index ec64b7acd..d2301018a 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md @@ -12,6 +12,14 @@ ms.localizationpriority: medium # PlayFab Multiplayer C++ SDK release notes +## 1.8.7 + +February 26, 2026 + +### Bug fixes + +- Fixed an issue where the library may crash after losing a WebSocket connection while paused in a debugger. + ## 1.8.6 February 13, 2026 diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-logging.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-logging.md index 73b8d1ac2..361af022f 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-logging.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-logging.md @@ -1,7 +1,7 @@ --- -title: Diagnostic tracing/logging in Azure PlayFab Lobby and Matchmaking SDKs +title: Diagnostic tracing/logging in PlayFab Lobby and Matchmaking SDKs author: vicodex -description: Learn about tracing/logging in the SDKs for Azure PlayFab Lobby and Matchmaking. +description: Learn about tracing/logging in the SDKs for PlayFab Lobby and Matchmaking. ms.author: victorku ms.date: 10/26/2022 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, networking, party, sdk, sample ms.localizationpriority: medium --- -# Tracing/logging instructions for Azure Playfab Lobby and Matchmaking SDKs +# Tracing/logging instructions for PlayFab Lobby and Matchmaking SDKs -This topic describes how to capture diagnostic traces generated by the Azure PlayFab Lobby and Matchmaking SDKs. +This topic describes how to capture diagnostic traces generated by the PlayFab Lobby and Matchmaking SDKs. > [!NOTE] > Our SDKs undergo internal testing before every release to ensure the expected level of functionality and normally don't require logging to be enabled by default, particularly in the shipping version of your game. diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md index 6522f75fc..2e2ffc15e 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Lobby and Matchmaking SDKs +title: PlayFab Lobby and Matchmaking SDKs author: PushpadantK -description: Learn about the SDKs for Azure PlayFab Lobby and Matchmaking. +description: Learn about the SDKs for PlayFab Lobby and Matchmaking. ms.author: pkacha ms.date: 11/30/2021 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, matchmaking, lobby, sdk, sample ms.localizationpriority: medium --- -# Azure Playfab Lobby and Matchmaking SDKs +# PlayFab Lobby and Matchmaking SDKs -This article describes all the Azure PlayFab Lobby and Matchmaking SDKs that are currently available. +This article describes all the PlayFab Lobby and Matchmaking SDKs that are currently available. If you don't find what you need, let us know by writing a post on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started.md index fb24b18cd..310576813 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Multiplayer getting started for Unity +title: PlayFab Multiplayer getting started for Unity author: victorku -description: Quickstart for Azure PlayFab Multiplayer Unity plugin. +description: Quickstart for PlayFab Multiplayer Unity plugin. ms.author: victorku ms.date: 11/23/2021 ms.topic: article diff --git a/playfab-docs/multiplayer/lobby/lobby-properties.md b/playfab-docs/multiplayer/lobby/lobby-properties.md index 5fd575953..b1fb5f106 100644 --- a/playfab-docs/multiplayer/lobby/lobby-properties.md +++ b/playfab-docs/multiplayer/lobby/lobby-properties.md @@ -1,5 +1,5 @@ --- -title: Azure PlayFab Lobby custom properties +title: PlayFab Lobby custom properties author: joannaleecy description: Learn about custom properties in Lobby. ms.author: jenelleb @@ -15,34 +15,34 @@ ms.localizationpriority: medium This article describes custom properties stored on the lobby. Use this functionality to store metadata about the game sessions that your lobby's represent. -## Pre-defined properties +## Predefined properties -Each lobby has a set of pre-defined properties commonly needed for most game scenarios. +Each lobby has a set of predefined properties commonly needed for most game scenarios. | Property | Definition | |--------------|-------------------| -| lobbyId | This is the unique identifier for a lobby. It can be used to distinguish between multiple lobbies that a player may be a part of. | -| connectionString | The identifier used to join the lobby. It is provided by the Lobby service. When an invite is sent to other players, the __connectionString__ is sent as the invitation. | +| lobbyId | This is the unique identifier for a lobby. It can be used to distinguish between multiple lobbies that a player might be a part of. | +| connectionString | The identifier used to join the lobby. It's provided by the Lobby service. When an invite is sent to other players, the __connectionString__ is sent as the invitation. | | maxMemberCount | The maximum number of players allowed in the lobby. This property can only be changed by owner. | -| owner | The entity that owns the lobby. Some lobbies may temporarily be ownerless in some circumstances. To learn more, see [Ownership changes](ownership-changes.md). | -| ownerMigrationPolicy | Policy determines how a new owner will be chosen. To learn more, see [Ownership changes](ownership-changes.md). | +| owner | The entity that owns the lobby. Some lobbies might be temporarily ownerless in some circumstances. To learn more, see [Ownership changes](ownership-changes.md). | +| ownerMigrationPolicy | Policy determines how a new owner is chosen. To learn more, see [Ownership changes](ownership-changes.md). | | accessPolicy | Policy indicates who can discover the lobby's connection string. This property can only be changed by the owner. | -| membershipLock | This value indicates whether new members may join the lobby or not. When __Locked__, new members may not join. When __Unlocked__ new members may join. This property can only be changed by the owner. | +| membershipLock | This value indicates whether new members can join the lobby or not. When __Locked__, new members can't join. When __Unlocked__ new members can join. This property can only be changed by the owner. | | RestrictInvitesToLobbyOwner | A setting that controls whether only the lobby owner can send invites to join the lobby. When true, only the lobby owner can send invites. When false or not specified, any member can send invites. Defaults to false if not specified. Restricted to client owned lobbies.| ## Custom Properties -There are 3 types of custom properties that titles can define. +There are three types of custom properties that titles can define. 1. Custom lobby properties * These properties apply to the whole lobby. * Only members of the lobby can see these properties. * Only the owner of the lobby can change these properties. 2. Custom member properties - * There is a unique map of member properties for each member in the lobby + * There's a unique map of member properties for each member in the lobby * Only members of the lobby can see these properties. * All members of the lobby can see every other members' properties. - * Each member may modify their own member properties but cannot modify another member's properties. + * Each member may modify their own member properties but can't modify another member's properties. * Once a member leaves the lobby, their member properties are deleted from the lobby. 3. Custom search properties. * These are special properties which can be used by all players in your title to search for lobbies matching a specific criteria. diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies.md index 72f58d7ea..a12fbddd2 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerfindlobbies.md @@ -31,7 +31,7 @@ The handle of the PFMultiplayer API instance. **`searchingEntity`**   [PFEntityKey*](../../pfmultiplayer/pfentitykey_clientsdk.md) -The playfab entity performing the search. +The PlayFab entity performing the search. **`searchConfiguration`**   [PFLobbySearchConfiguration*](../structs/pflobbysearchconfiguration.md) diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md index 0fba0672e..4e032f1ff 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md @@ -36,8 +36,8 @@ ms.date: 11/15/2023 | [PFMatchmakingMatchMember](structs/pfmatchmakingmatchmember.md) | A member of a match result. | | [PFMatchmakingServerBackfillTicketConfiguration](structs/pfmatchmakingserverbackfillticketconfiguration.md) | Defines the configuration for a server backfill ticket. | | [PFMatchmakingTicketConfiguration](structs/pfmatchmakingticketconfiguration.md) | Defines the configuration for a matchmaking ticket. | -| [PFMultiplayerPort](structs/pfmultiplayerport.md) | A port used by a Playfab Multiplayer Server. | -| [PFMultiplayerServerDetails](structs/pfmultiplayerserverdetails.md) | Details about a Playfab Multiplayer Server. | +| [PFMultiplayerPort](structs/pfmultiplayerport.md) | A port used by a PlayFab Multiplayer Server. | +| [PFMultiplayerServerDetails](structs/pfmultiplayerserverdetails.md) | Details about a PlayFab Multiplayer Server. | ## State changes diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerport.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerport.md index dd5e35fc2..0d3b802e3 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerport.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerport.md @@ -1,7 +1,7 @@ --- author: ScottMunroMS title: "PFMultiplayerPort" -description: "A port used by a Playfab Multiplayer Server." +description: "A port used by a PlayFab Multiplayer Server." ms.author: scmunro ms.topic: reference ms.service: azure-playfab @@ -10,7 +10,7 @@ ms.date: 08/16/2022 # PFMultiplayerPort -A port used by a Playfab Multiplayer Server. +A port used by a PlayFab Multiplayer Server. ## Syntax diff --git a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails.md b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails.md index 5fc72cf74..90bed0ce8 100644 --- a/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails.md +++ b/playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmultiplayerserverdetails.md @@ -1,7 +1,7 @@ --- author: ScottMunroMS title: "PFMultiplayerServerDetails" -description: "Details about a Playfab Multiplayer Server." +description: "Details about a PlayFab Multiplayer Server." ms.author: scmunro ms.topic: reference ms.service: azure-playfab @@ -10,7 +10,7 @@ ms.date: 08/16/2022 # PFMultiplayerServerDetails -Details about a Playfab Multiplayer Server. +Details about a PlayFab Multiplayer Server. ## Syntax @@ -29,12 +29,12 @@ struct PFMultiplayerServerDetails { **`fqdn`**   const char* *is null-terminated* -The fully qualified domain name of the virtual machine that is hosting this multiplayer server. +The fully qualified domain name of the virtual machine that's hosting this multiplayer server. **`ipv4Address`**   const char* *is null-terminated* -The IPv4 address of the virtual machine that is hosting this multiplayer server. +The IPv4 address of the virtual machine that's hosting this multiplayer server. **`ports`**   const [PFMultiplayerPort](pfmultiplayerport.md)* diff --git a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort.md b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort.md index a5e64037c..f5dfe9cdd 100644 --- a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort.md +++ b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort.md @@ -10,7 +10,7 @@ ms.date: 08/18/2022 # Class MultiplayerPort -A port used by a Playfab Multiplayer Server. +A port used by a PlayFab Multiplayer Server. ```csharp public class MultiplayerPort @@ -20,7 +20,7 @@ public class MultiplayerPort | name | description | | --- | --- | -| [MultiplayerPort](MultiplayerPort/MultiplayerPort.md)(…) | A port used by a Playfab Multiplayer Server. | +| [MultiplayerPort](MultiplayerPort/MultiplayerPort.md)(…) | A port used by a PlayFab Multiplayer Server. | | [Name](MultiplayerPort/Name.md) { get; set; } | The name of the port as specified in the PlayFab Game Manager server settings. | | [Num](MultiplayerPort/Num.md) { get; set; } | The number for the port. | | [Protocol](MultiplayerPort/Protocol.md) { get; set; } | The protocol for the port. | diff --git a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort/MultiplayerPort.md b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort/MultiplayerPort.md index 35ac2a1ad..82ce29cb9 100644 --- a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort/MultiplayerPort.md +++ b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerPort/MultiplayerPort.md @@ -10,7 +10,7 @@ ms.date: 08/18/2022 # MultiplayerPort constructor -A port used by a Playfab Multiplayer Server. +A port used by a PlayFab Multiplayer Server. ```csharp public MultiplayerPort(string name, uint num, MultiplayerProtocolType protocolType) diff --git a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails.md b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails.md index d1f0e45dd..a4c011004 100644 --- a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails.md +++ b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails.md @@ -10,7 +10,7 @@ ms.date: 08/18/2022 # Class MultiplayerServerDetails -Details about a Playfab Multiplayer Server. +Details about a PlayFab Multiplayer Server. ```csharp public class MultiplayerServerDetails @@ -20,9 +20,9 @@ public class MultiplayerServerDetails | name | description | | --- | --- | -| [MultiplayerServerDetails](MultiplayerServerDetails/MultiplayerServerDetails.md)(…) | Details about a Playfab Multiplayer Server. | -| [Fqdn](MultiplayerServerDetails/Fqdn.md) { get; set; } | The fully qualified domain name of the virtual machine that is hosting this multiplayer server. | -| [Ipv4Address](MultiplayerServerDetails/Ipv4Address.md) { get; set; } | The IPv4 address of the virtual machine that is hosting this multiplayer server. | +| [MultiplayerServerDetails](MultiplayerServerDetails/MultiplayerServerDetails.md)(…) | Details about a PlayFab Multiplayer Server. | +| [FQDN](MultiplayerServerDetails/Fqdn.md) { get; set; } | The fully qualified domain name of the virtual machine that's hosting this multiplayer server. | +| [Ipv4Address](MultiplayerServerDetails/Ipv4Address.md) { get; set; } | The IPv4 address of the virtual machine that's hosting this multiplayer server. | | [Ports](MultiplayerServerDetails/Ports.md) { get; set; } | The ports the multiplayer server uses. | | [Region](MultiplayerServerDetails/Region.md) { get; set; } | The server's region. | diff --git a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails/MultiplayerServerDetails.md b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails/MultiplayerServerDetails.md index da7eb5f70..b87c27700 100644 --- a/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails/MultiplayerServerDetails.md +++ b/playfab-docs/multiplayer/lobby/unity-multiplayer-api-reference/PlayFab.Multiplayer/MultiplayerServerDetails/MultiplayerServerDetails.md @@ -10,7 +10,7 @@ ms.date: 08/18/2022 # MultiplayerServerDetails constructor -Details about a Playfab Multiplayer Server. +Details about a PlayFab Multiplayer Server. ```csharp public MultiplayerServerDetails(string fqdn, string ipv4Address, IList ports, @@ -19,8 +19,8 @@ public MultiplayerServerDetails(string fqdn, string ipv4Address, IList [!NOTE] > Our SDKs undergo internal testing before every release to ensure the expected level of functionality and normally don't require logging to be enabled by default, particularly in the shipping version of your game. > -> However, sometimes it may be needed to capture and share produced logs with Microsoft for troubleshooting and diagnostic purposes. +> However, sometimes it might be needed to capture and share produced logs with Microsoft for troubleshooting and diagnostic purposes. -The type of logs and the way logging should be configured/captured depends on a platform. Our middleware SDKs (Unity and Unreal) use Party C++ SDKs as an underlying dependency component, and a process of configuring/capturing logs for them is the same or very similar to the process for a corresponding C++ SDK. All necessary instructions and pointers are listed in the table below: +The type of logs and the way logging should be configured/captured depends on a platform. Our middleware SDKs (Unity and Unreal) use Party C++ SDKs as an underlying dependency component, and a process of configuring/capturing logs for them is the same or similar to the process for a corresponding C++ SDK. All necessary instructions and pointers are listed in the table below: ## Per platform logging instructions @@ -27,7 +27,7 @@ The type of logs and the way logging should be configured/captured depends on a |------------|------------|------------| | Android | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `Android` in a table under that section. | | iOS | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `iOS` in a table under that section. | -| MacOS | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `macOS` in a table under that section. | +| macOS | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `macOS` in a table under that section. | | Linux | Plain text | See [`Logging` section of this `README.md` file](https://github.com/PlayFab/PlayFabParty#logging) and `Linux` in a table under that section. | | Switch | Plain text | See `Logging` section of `README.md` file included in a NuGet package for this SDK. | | PlayStation 4 | Plain text | See `Logging` section of `README.md` file included in a NuGet package for this SDK. | diff --git a/playfab-docs/multiplayer/networking/party-playstream-events.md b/playfab-docs/multiplayer/networking/party-playstream-events.md index 37784903e..84d425694 100644 --- a/playfab-docs/multiplayer/networking/party-playstream-events.md +++ b/playfab-docs/multiplayer/networking/party-playstream-events.md @@ -1,6 +1,6 @@ --- title: PlayFab Party PlayStream Events -description: Microsoft Azure PlayFab PlayStream events generated by the Party real-time chat and data communication API. +description: Microsoft PlayFab PlayStream events generated by the Party real-time chat and data communication API. author: joannaleecy ms.author: jenelleb ms.date: 08/16/2019 diff --git a/playfab-docs/multiplayer/networking/party-samples.md b/playfab-docs/multiplayer/networking/party-samples.md index e66836897..a38fb82fc 100644 --- a/playfab-docs/multiplayer/networking/party-samples.md +++ b/playfab-docs/multiplayer/networking/party-samples.md @@ -1,7 +1,7 @@ --- title: Party samples author: joannaleecy -description: Learn about the samples for Azure PlayFab Party. +description: Learn about the samples for PlayFab Party. ms.author: jenelleb ms.date: 10/13/2020 ms.topic: article @@ -12,7 +12,7 @@ ms.localizationpriority: medium # Party samples -This topic lists all the Azure PlayFab Party samples that are currently available. +This topic lists all the PlayFab Party samples that are currently available. If there's a specific sample that you'd like to have, let us know by writing a post on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/multiplayer/networking/party-sdks.md b/playfab-docs/multiplayer/networking/party-sdks.md index b645d853c..7f75e62c5 100644 --- a/playfab-docs/multiplayer/networking/party-sdks.md +++ b/playfab-docs/multiplayer/networking/party-sdks.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Party SDKs +title: PlayFab Party SDKs author: joannaleecy -description: Learn about the SDKs for Azure PlayFab Party. +description: Learn about the SDKs for PlayFab Party. ms.author: jenelleb ms.date: 02/22/2021 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, networking, party, sdk, sample ms.localizationpriority: medium --- -# Azure Playfab Party SDKs +# PlayFab Party SDKs -This topic describes all the Azure PlayFab Party SDKs that are currently available. +This topic describes all the PlayFab Party SDKs that are currently available. If you don't find what you need, let us know by writing a post on our [forums](https://community.playfab.com/index.html). diff --git a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md index 1776e3198..2793b06dd 100644 --- a/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md +++ b/playfab-docs/multiplayer/networking/party-unreal-engine-oss-quickstart.md @@ -11,7 +11,7 @@ keywords: playfab, multiplayer, networking, unreal, unreal engine, unreal engine # QuickStart: PlayFab Online Subsystem -This article helps you set up and use Azure PlayFab Multiplayer features like Lobby, Matchmaking, and Party for games built with Unreal Engine 4 or Unreal Engine 5. For the full list of supported platforms and versions in Unreal Engine 4 or Unreal Engine 5, see [Supported platforms](party-unreal-engine-oss-overview.md). +This article helps you set up and use PlayFab Multiplayer features like Lobby, Matchmaking, and Party for games built with Unreal Engine 4 or Unreal Engine 5. For the full list of supported platforms and versions in Unreal Engine 4 or Unreal Engine 5, see [Supported platforms](party-unreal-engine-oss-overview.md). After following the relevant steps that are outlined in this page for your target platforms, you'll be ready to start using the PlayFab Online Subsystem (PF OSS). Authentication, networking, VOIP, grouping into lobbies, and matchmaking is handled on your behalf with no other changes required. diff --git a/playfab-docs/multiplayer/networking/release-notes.md b/playfab-docs/multiplayer/networking/release-notes.md index f18730d59..68de2998d 100644 --- a/playfab-docs/multiplayer/networking/release-notes.md +++ b/playfab-docs/multiplayer/networking/release-notes.md @@ -13,10 +13,19 @@ ms.localizationpriority: medium # PlayFab Party Release Notes > [!NOTE] -> Support for the XDK and Windows 7 platforms ended on August 1, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using Windows 7 or XDK versions of the PlayFab Party library. +> Support for the XDK and Windows 7 platforms ended on August 1, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services continue to operate with no impact to any titles currently using Windows 7 or XDK versions of the PlayFab Party library. > [!NOTE] -> Support for 32-bit Android platforms (arm7 and x86) ended on October 19th, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using the PlayFab Party library on 32-bit Android platforms. +> Support for 32-bit Android platforms (arm7 and x86) ended on October 19, 2023. No new PlayFab Party library updates will be released for those platforms. The PlayFab Party networking and voice services will continue to operate with no impact to any titles currently using the PlayFab Party library on 32-bit Android platforms. + +## 1.10.17 + +February 23, 2026 + +- Android: Fix Bluetooth microphones not working. +- Linux: Remove SafeStack. +- Apple: Hide OpenSSL symbols from Party. +- Nintendo Switch 2: Resolved TCP connection error when IP changes. ## 1.10.16 @@ -33,14 +42,14 @@ February 2, 2026 December 17, 2025 -- Nintendo Switch 2: Added 10 second timeout for webrequests. +- Nintendo Switch 2: Added 10-second timeout for web requests. ## 1.10.14 December 9, 2025 -- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has actually expired. -- Android: Added support for 16 KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). +- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has expired. +- Android: Added support for 16-KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). ## 1.10.13 @@ -48,14 +57,14 @@ December 9, 2025 October 14, 2025 - Fixed an issue that caused the microphone to not function properly on iOS 26. -- Apple: Added support for Arm64 .xcframework on iOS. +- Apple: Added support for Arm64.xcframework on iOS. ## 1.10.12 October 6, 2025 -- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has actually expired. -- Android: Added support for 16 KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). +- Changed the [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md) PartyStatusChangeResult behavior to return `PartyServiceError` for transient errors that occur before the token expires, and to return `UserNotAuthorized` only when the token has expired. +- Android: Added support for 16-KB page sizes to satisfy the new [Android page size requirements](https://developer.android.com/guide/practices/page-sizes). - Apple: Added support for Arm64 simulator builds on iOS. ### Bug fixes @@ -75,34 +84,34 @@ March 11, 2025 January 24, 2025 -- PlayStation®4 and, PlayStation®5: Resolved a crash related to profanity masking on PlayStation platforms. +- PlayStation®4 and PlayStation®5: Resolved a crash related to profanity masking on PlayStation platforms. ## 1.10.6 December 10, 2024 -- PlayStation®4 and, PlayStation®5: Resolved build warnings and errors for integration with C++14 and above. +- PlayStation®4 and PlayStation®5: Resolved build warnings and errors for integration with C++14 and later versions. ## 1.10.5 November 18, 2024 -- Fixed an issue where voice chat would sometimes not work for users remaining in a Party network after other users rejoined and left multiple times. +- Fixed an issue where voice chat sometimes didn't work for users who stayed in a Party network after other users rejoined and left multiple times. - Fixed an issue where [PartyLocalEndpoint::GetEndpointStatistics](reference/classes/PartyLocalEndpoint/methods/partylocalendpoint_getendpointstatistics.md) would report incorrect values for [PartyEndpointStatistic::CurrentlyQueuedSendMessages](reference/enums/partyendpointstatistic.md) and [PartyEndpointStatistic::CurrentlyQueuedSendMessageBytes](reference/enums/partyendpointstatistic.md) when used with direct peer connections. -- Fixed broken symlinks for the framework on the macOS. -- Improved handling log exceptions for non Windows platforms during collection of SDK logs. +- Fixed broken symlinks for the framework on macOS. +- Improved handling of log exceptions for non-Windows platforms during collection of SDK logs. ## 1.10.4 November 12, 2024 -- PlayStation®4 and, PlayStation®5: Resolved crashes related to mutex operations and endpoint state changes during creation and destruction. +- PlayStation®4 and PlayStation®5: Resolved crashes related to mutex operations and endpoint state changes during creation and destruction. ## 1.10.3 October 14, 2024 -- Added support for up to 128 devices per network. For more details, see [Scalable networks](party-features.md#scalable-networks-up-to-128-devices-per-network). +- Added support for up to 128 devices per network. For more information, see [Scalable networks](party-features.md#scalable-networks-up-to-128-devices-per-network). - Increased `c_maxNetworkConfigurationMaxDeviceCount` from 32 to 128. - Updated internal diagnostics. - Updated build settings for security hardening. @@ -114,27 +123,27 @@ September 18, 2024 ### Bug fixes -- Fixed an issue where the library may crash when establishing direct peer connections in networks with three or more devices. +- Fixed an issue where the library might crash when it establishes direct peer connections in networks with three or more devices. ## 1.10.0 August 5, 2024 -- Added support for game_server entities, so servers can connect to Party networks via the SDK and be securely identified by game clients. After authenticating a `game_server` entity via AuthenticateGameServerWithCustomId, it can be added as a local user via [PartyManager::CreateLocalUserWithEntityType](reference/classes/PartyManager/methods/partymanager_createlocaluserwithentitytype.md). +- Added support for `game_server` entities, so servers can connect to Party networks via the SDK and be securely identified by game clients. After authenticating a `game_server` entity via `AuthenticateGameServerWithCustomId`, it can be added as a local user via [PartyManager::CreateLocalUserWithEntityType](reference/classes/PartyManager/methods/partymanager_createlocaluserwithentitytype.md). - Added methods for determining the entity type associated with each entity in the library. For more information, see [PartyLocalUser::GetEntityType](reference/classes/PartyLocalUser/methods/partylocaluser_getentitytype.md), [PartyEndpoint::GetEntityType](reference/classes/PartyEndpoint/methods/partyendpoint_getentitytype.md), and [PartyChatControl::GetEntityType](reference/classes/PartyChatControl/methods/partychatcontrol_getentitytype.md). - Added a direct peer connectivity option that enables direct peer connections between `title_player` and `game_server` entities while disallowing direct peer connections between `title_player` entities and other `title_player` entities. For more information, see [PartyDirectPeerConnectivityOptions::OnlyServers](reference/enums/partydirectpeerconnectivityoptions.md). - Added methods to retrieve a convenient list of endpoints based on filters. For more information, see [PartyNetwork::GetEndpointsByUserType](reference/classes/PartyNetwork/methods/partynetwork_getendpointsbyusertype.md). -- Memory allocations by third party libraries used in PlayFab Party on PlayStation®4 and, PlayStation®5 that were using default allocators have been updated to use Party's memory callbacks. Titles using [PartyManager::SetMemoryCallbacks](reference/classes/PartyManager/methods/partymanager_setmemorycallbacks.md) to configure title-specific memory allocation functions allocations will now see and have control over these allocations. +- Updated memory allocations by third party libraries used in PlayFab Party on PlayStation®4 and, PlayStation®5 that were using default allocators have been updated to use Party's memory callbacks. Titles using [PartyManager::SetMemoryCallbacks](reference/classes/PartyManager/methods/partymanager_setmemorycallbacks.md) to configure title-specific memory allocation functions allocations will now see and have control over these allocations. ### Bug fixes -- Fixed an issue where the library may crash on Windows or Xbox while the process is terminating. +- Fixed an issue where the library might crash on Windows or Xbox while the process is terminating. - Addressed spurious direct peer connection failures after a previous connection attempt failed in certain cases for non Windows platforms. -- Fixed an issue where the DestroyNetwork event was not fired during repeated Party network creation and destroying. +- Fixed an issue where the DestroyNetwork event wasn't fired during repeated Party network creation and destroying. ### Known issues -- The library may occasionally crash when establishing direct peer connections in networks with three or more devices. +- The library might occasionally crash when establishing direct peer connections in networks with three or more devices. ## 1.9.5 @@ -177,13 +186,13 @@ February 5, 2024 November 13, 2023 -- Fixed a bug where a crash may occur when a client tries to leave a network on Nintendo Switch. +- Fixed a bug where a crash might occur when a client tries to leave a network on Nintendo Switch. ## 1.8.10 October 19, 2023 -This release updates the minimum SDK versioning and target SDK versioning for PlayFab Party Apple and Android platforms. +This release updates the minimum SDK version and target SDK version for PlayFab Party Apple and Android platforms. For Apple platforms, we follow [Apple's Xcode guidelines](https://developer.apple.com/support/xcode/) with the release of Xcode 15. - iOS @@ -210,7 +219,7 @@ October 20, 2023 - Implemented shared properties for endpoints. Shared properties may be set when creating an endpoint via [`PartyNetwork::CreateEndpoint`](reference/classes/PartyNetwork/methods/partynetwork_createendpoint.md). A shared property may be retrieved using [`PartyEndpoint::GetSharedProperty`](reference/classes/PartyEndpoint/methods/partyendpoint_getsharedproperty.md). -- Improved audio packet queueing to reduce perceived chat audio latency in some scenarios. +- Improved audio packet queuing to reduce perceived chat audio latency in some scenarios. - Upgraded internal version of the Opus codec. - Fixed a low frequency crash. - Improved internal diagnostics. @@ -226,7 +235,7 @@ June 28, 2023 ### Bug fixes -- Fixed a bug where [`PartyLocalChatControl::SetAudioRenderVolume`](reference/classes/PartyLocalChatControl/methods/partylocalchatcontrol_setaudiorendervolume.md) would not properly work for Nintendo Switch, PlayStation®4 and, PlayStation®5. +- Fixed a bug where [`PartyLocalChatControl::SetAudioRenderVolume`](reference/classes/PartyLocalChatControl/methods/partylocalchatcontrol_setaudiorendervolume.md) wouldn't properly work for Nintendo Switch, PlayStation®4 and, PlayStation®5. “PlayStation” is a registered trademark or trademark of Sony Interactive Entertainment Inc. @@ -251,7 +260,7 @@ May 8, 2023 - iOS, Android: Added support for enabling noise suppression on audio captured from a local chat control. For more information, see [`PartyLocalChatControl::SetVoiceAudioOptions`](reference/classes/PartyLocalChatControl/methods/partylocalchatcontrol_setvoiceaudiooptions.md). ### Bug fixes -- Fixed a bug where the library may leak memory due to internal diagnostic tracking when the user's entity token expires. +- Fixed a bug where the library could leak memory due to internal diagnostic tracking when the user's entity token expires. ## 1.7.23 @@ -264,8 +273,8 @@ April 1, 2023 March 30, 2023 ### Bug fixes -- Fixed a bug where Party could crash if it was not cleaned up before the host process started exiting. -- Changed behavior for peer-to-peer connection to fallback to a relayed connection if the link is disconnected unexpectedly. The previous behavior would disconnect both the devices from the network. +- Fixed a bug where Party could crash if it wasn't cleaned up before the host process started exiting. +- Changed behavior for peer-to-peer connection to fall back to a relayed connection if the link is disconnected unexpectedly. The previous behavior would disconnect both the devices from the network. ## 1.7.20 @@ -273,7 +282,7 @@ February 8, 2023 ### Bug fixes -- Fixed a bug where audio from 44.1 kHz microphones may sound distorted. +- Fixed a bug where audio from 44.1-kHz microphones may sound distorted. - Improved diagnostic error messages for network errors reported by [PartyManager::GetErrorMessage()](reference/classes/PartyManager/methods/partymanager_geterrormessage.md). ## 1.7.19 @@ -290,8 +299,8 @@ October 7, 2022 ### Bug fixes -- Fixed a bug where a crash may occur when a chat control is connect to a network on iOS. -- Fixed a bug where a crash may occur when enabling iOS log. +- Fixed a bug where a crash might occur when a chat control is connected to a network on iOS. +- Fixed a bug where a crash might occur when enabling iOS log. ## 1.7.16 @@ -302,7 +311,7 @@ September 27, 2022 - Added .bundle for Unity plug-in loading and native macOS development. ### Bug fixes -- Fixed a bug where a crash may occur when enabling macOS log. +- Fixed a bug where a crash might occur when enabling macOS log. ## 1.7.14 @@ -310,7 +319,7 @@ August 12, 2022 ### New SDKs for Linux and macOS -- Added native support for PlayFab Party on Linux and macOS, enabling game developers to create cross-platform or multiplatform real-time multiplayer experiences on even more platforms. For links to these and other SDK releases,see [Azure Playfab Party SDKs](party-sdks.md). +- Added native support for PlayFab Party on Linux and macOS, enabling game developers to create cross-platform or multiplatform real-time multiplayer experiences on even more platforms. For links to these and other SDK releases, see [PlayFab Party SDKs](party-sdks.md). August 11, 2022 @@ -353,8 +362,8 @@ February 8, 2022 September 30, 2021 ### Bug fixes -- Fixed an issue where some 16kHz microphones weren't working. -- Fixed an issue where microphone permission changes were not handled on Windows. +- Fixed an issue where some 16 kHz microphones weren't working. +- Fixed an issue where microphone permission changes weren't handled on Windows. - Fixed a memory leak in some `PartyManager::CreateNewNetwork()` failure conditions. - Fixed an occasional crash in `PartyLocalEndpoint::GetEndpointStatistics()`. @@ -374,13 +383,13 @@ June 29, 2021 ### Bug fixes -- Fixed a bug where a crash may occur when a chat control is connected to a network while that same chat control is disconnecting from another network. +- Fixed a bug where a crash might occur when a chat control connects to a network while that same chat control is disconnecting from another network. ## 1.6.0 April 12, 2021 ### New thread control and text moderation features -- The library's work can now be run manually on game-controlled threads. For more information, see [`PartyManager::SetWorkMode`](reference/classes/PartyManager/methods/partymanager_setworkmode.md). +- The library's work can now run manually on game-controlled threads. For more information, see [`PartyManager::SetWorkMode`](reference/classes/PartyManager/methods/partymanager_setworkmode.md). - Offensive text chat can now optionally be filtered. For more information, see [Using text moderation](../../community/voice-communications/concepts-text-moderation.md). ### Explicit enum numbering in the header @@ -391,26 +400,27 @@ April 12, 2021 March 26, 2021 ### Bug fixes -- Fixed a bug where audio is cutting out on iOS devices using Bluetooth headsets. +- Fixed a bug where audio cuts out on iOS devices using Bluetooth headsets. - Fixed a bug where an incorrect error code is generated when the app doesn't have permission to activate a microphone on Windows platforms. -- Fixed a bug where an unhealthy device is never refreshed unless something else forces a refresh. -- Fixed a bug where a crash may occur when dereferencing a send channel's user data after the source endpoint associated with that channel has become invalid. +- Fixed a bug where an unhealthy device isn't refreshed unless something else forces a refresh. +- Fixed a bug where a crash might occur when dereferencing a send channel's user data after the source endpoint associated with that channel becomes invalid. - Fixed a bug where clients experience silent failures if a remote chat control doesn't have a language code. ## 1.5.10 ### Bug fixes -- Fixed a bug where the library may fail to initialize on some Windows devices due to a mismatch between the processor affinity of the process and the library's default thread affinity. -- Fixed a bug where the library may not provide errors when an operation fails due to an internal web request failure. -- Fixed a bug where a crash may occur when direct peer connectivity is enabled and the library attempts to establish direct peer connectivity to another device. -- Fixed a bug that may result in crackling or distorted audio. +- Fixed a bug where the library might fail to initialize on some Windows devices due to a mismatch between the processor affinity of the process and the library's default thread affinity. +- Fixed a bug where the library might not provide errors when an operation fails due to an internal web request failure. +- Fixed a bug where a crash might occur when direct peer connectivity is enabled and the library attempts to establish direct peer connectivity to another device. +- Fixed a bug that might result in crackling or distorted audio. ## 1.5.1 September 05, 2020 + ### Bug fix -- Fixed a bug where the library may fail to activate the microphone on iOS. +- Fixed a bug where the library fails to activate the microphone on iOS. ## 1.5.0 @@ -438,7 +448,7 @@ April 30, 2020 - The transcription stack has been updated to use TLS1.2 on Windows 7, Android, and iOS. Upgrade if you make use of any of these platforms as TLS1.1 support will be deprecated by [Azure Speech Services](https://azure.microsoft.com/updates/azuretls12/) beginning in September 2020. All other platforms already support TLS1.2 and no upgrade is necessary. ### Bug fixes -- Fixed a bug where the `languageCode` field in the `PartyCreateChatControlCompletedStateChange` struct was not being populated. +- Fixed a bug where the `languageCode` field in the `PartyCreateChatControlCompletedStateChange` struct wasn't being populated. - Fixed a bug that was artificially inflating the latency measurements reported by `PartyManager::GetRegions()`. - Fixed a bug that allowed `PartyManager::SetMemoryCallbacks()` to be called at unsafe times. - Fixed a bug where calling `PartyManager::DestroyLocalUser()` with a `PartyLocalUser` in a `PartyNetwork` would generate a `PartyLocalUserRemovedStateChange` with an incorrect value in the removedReason field, `PartyLocalUserRemovedReason::RemoveLocalUser`, instead of the correct value, `PartyLocalUserRemovedReason::DestroyLocalUser`. @@ -451,12 +461,12 @@ April 30, 2020 - Typos in the header documentation have been fixed. - A more descriptive error code and error message are now provided when an invalid region is passed to `PartyManager::CreateNewNetwork()`. - The documentation for the lifetimes of `PartyString` values has been clarified for the structures and interfaces in Party.h. -- The documentation for `PartyManager::Cleanup()` was clarified to explain it is not a thread-safe call. +- The documentation for `PartyManager::Cleanup()` was clarified to explain it isn't a thread-safe call. - A more descriptive error code and error message are provided when `PartyManager::ConnectToNetwork()` asynchronously fails with internet connectivity errors. ## 1.3.0 -### Chat API Changes +### Chat API changes * The real-time audio manipulation functions, which can be used to modify outgoing or incoming voice chat audio, are implemented for Windows and Xbox. For more information, see [Using real-time audio manipulation to apply custom voice effects](../../community/voice-communications/concepts-realtime-audio-manipulation.md). * The chat permission options have more options for optionally configuring text-to-speech and microphone audio permissions independently. For more information, see [`PartyChatPermissionOptions`](reference/enums/partychatpermissionoptions.md). @@ -466,24 +476,24 @@ April 30, 2020 ## 1.2.2 -### iOS Changes +### iOS changes - Adds support for the volume control API. ## 1.2.0 -### Android Changes +### Android changes - Adds support for the volume control API. -- Removes audio focus handling from the library. Host applications are now expected to implement their own focus handling logic. +- Removes audio focus handling from the library. Host applications are now expected to implement their own focus handling logic. ## 1.0.2 -- Fixed crash in background telemetry +- Fixed crash in background telemetry. ## 1.0.1 -### Party API Changes +### Party API changes #### PartyManager::SetMemoryCallbacks Changes @@ -495,27 +505,27 @@ The `PartyStateChangeResult` value `TitleCreateNetworkThrottled` has been remove ## 0.7.0-prerelease -### Windows Packaging Changes +### Windows packaging changes This release of Party introduces a new NuGet package, [Microsoft.PlayFab.PlayFabParty.Cpp.Windows](https://www.nuget.org/packages/Microsoft.PlayFab.PlayFabParty.Cpp.Windows), which replaces and deprecates the NuGet packages specific to Windows 10 and Windows 7 (Microsoft.PlayFab.PlayFabParty.Cpp.Win10 and Microsoft.PlayFab.PlayFabParty.Cpp.Win7, respectively). The new unified Windows NuGet package contains two new DLLs, PartyWin.dll (supports Windows 8.1 and up) and PartyWin7.dll (only for use on Windows 7). With the new Windows unified NuGet package, the correct Party DLL is loaded based on runtime detection of the OS version, so both PartyWin.dll and PartyWin7.dll should be included in the game distribution package. -### Android Changes +### Android changes The Android flavor now uses a shared object for Party (libparty.so) instead of a static library (libparty.a). This release also contains Android-specific bug fixes for audio device selection. -### iOS Changes +### iOS changes The iOS flavor of Party now has the framework package included for dynamically loading libparty instead of the statically built libparty.a. -### API Changes +### API changes #### UpdateEntityToken API This release of Party makes a change related to the handling of PlayFab entity tokens. In the previous version, the game provided Party with a user's entity token in the `PartyManager::CreateLocalUser()` API. Thereafter, Party internally refreshed the entity token and kept it up to date. -In this version, the internal token refreshing behavior has been removed and replaced by a new API, `PartyLocalUser::UpdateEntityToken()`. The caller is now responsible for monitoring the expiration of the entity token provided to `PartyManager::CreateLocalUser()` and `PartyLocalUser::UpdateEntityToken()`. When the token is nearing or past the expiration time, a new token should be obtained by performing a PlayFab login operation and provided to the Party library by calling `PartyLocalUser::UpdateEntityToken()`. It is recommended to acquire a new token when the previously supplied token is halfway through its validity period. On platforms that may enter a low power state or pause application execution for a long time, the token may be prevented from being refreshed before it expires. The token should be checked for expiration once execution resumes. +In this version, the internal token refreshing behavior has been removed and replaced by a new API, `PartyLocalUser::UpdateEntityToken()`. The caller is now responsible for monitoring the expiration of the entity token provided to `PartyManager::CreateLocalUser()` and `PartyLocalUser::UpdateEntityToken()`. When the token is nearing or past the expiration time, a new token should be obtained by performing a PlayFab login operation and provided to the Party library by calling `PartyLocalUser::UpdateEntityToken()`. It's recommended to acquire a new token when the previously supplied token is halfway through its validity period. On platforms that enter a low power state or pause application execution for a long time, the token might be prevented from being refreshed before it expires. The token should be checked for expiration once execution resumes. The rough flow is as follows: @@ -527,14 +537,14 @@ The rough flow is as follows: 1. [New] Call `PartyLocalUser::UpdateEntityToken()` to pass in the new token to Party Additional notes: -- The act of acquiring an entity token does not invalidate any previously obtained entity tokens. They remain valid until they expire. +- The act of acquiring an entity token doesn't invalidate any previously obtained entity tokens. They remain valid until they expire. - The internal refreshing functionality was removed because most games are expected to make their own PlayFab calls. Having both the game and the Party library fetch entity tokens causes unnecessary service load to manage two sets of tokens. #### Chat API Changes The `PartyVoiceChatTranscriptionReceivedStateChange` now includes a `languageCode` field, which indicates the language of the transcription. -The `PartyChatTextReceivedStateChange` now includes a `languageCode` field, which may indicate the language of the chat text. The `languageCode` field will be populated when chat text translation has been enabled via `PartyLocalChatControl::SetTextChatOptions()`. +The `PartyChatTextReceivedStateChange` now includes a `languageCode` field, which indicates the language of the chat text. The `languageCode` field will be populated when chat text translation has been enabled via `PartyLocalChatControl::SetTextChatOptions()`. ## 0.6.0-prerelease @@ -549,12 +559,12 @@ For more information, see the following links: ## 0.5.0-prerelease -### API Changes +### API changes #### Accessible Chat * Added support for text-to-speech narration. (see `PartyLocalChatControl::SetTextToSpeechProfile()`) * Added more options for controlling when speech-to-text occurs. (see `PartyLocalChatControl::SetTranscriptionOptions()`) -* Added text-to-text translation to the API, although it is not yet supported. (see `PartyLocalChatControl::SetTextChatOptions()`) +* Added text-to-text translation to the API, although it isn't yet supported. (see `PartyLocalChatControl::SetTextChatOptions()`) * Reduced text-to-speech bandwidth and memory usage. #### Network access control @@ -563,13 +573,13 @@ For more information, see the following links: ## 0.4.6-prerelease -### API Changes +### API changes Added new public API `PartyLocalUser::UpdateEntityToken()`. ## 0.2.0-prerelease -### API Changes +### API changes * `PartyManager::Initialize` now requires a valid PlayFab Title ID to be passed in. diff --git a/playfab-docs/multiplayer/networking/unreal-release-notes.md b/playfab-docs/multiplayer/networking/unreal-release-notes.md index 3e5c86045..8e13b6146 100644 --- a/playfab-docs/multiplayer/networking/unreal-release-notes.md +++ b/playfab-docs/multiplayer/networking/unreal-release-notes.md @@ -130,8 +130,8 @@ Known issue: - To invite a Steam or PlayStation player, the host must be on the same platform. ## 2.0.0 -- UE4 engine OSS PlayFab is updated to use Multiplayer features offered by Azure PlayFab such as Lobby, Matchmaking along with PlayFab Party. -This update replaces the Xbox provided MPSD with Azure PlayFab Lobby and XBL Smart match with Azure Matchmaking service. +- UE4 engine OSS PlayFab is updated to use Multiplayer features offered by PlayFab such as Lobby, Matchmaking along with PlayFab Party. +This update replaces the Xbox provided MPSD with PlayFab Lobby and XBL Smart match with Azure Matchmaking service. - XDK is no longer supported for this version of the OSS. ## 1.0.7 diff --git a/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md b/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md index 2e0aaeb36..4f478179a 100644 --- a/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md +++ b/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md @@ -120,7 +120,7 @@ docker build -t customer5555555.azurecr.io/pvp_gameserver:v1 . 4. Upload the container image -Run the below commands to push the image to your Azure PlayFab Container registry. Select a meaningful and helpful name:tag combination for your uploaded container image. Then use [docker push](https://docs.docker.com/engine/reference/commandline/push/) or another container registry client, to upload your container to the Azure PlayFab operated registry. +Run the below commands to push the image to your PlayFab Container registry. Select a meaningful and helpful name:tag combination for your uploaded container image. Then use [docker push](https://docs.docker.com/engine/reference/commandline/push/) or another container registry client, to upload your container to the PlayFab operated registry. ```docker docker tag hello-world customer5555555.azurecr.io/pvp_gameserver:v1 diff --git a/playfab-docs/multiplayer/servers/directly-debugging-game-servers.md b/playfab-docs/multiplayer/servers/directly-debugging-game-servers.md index 528bba36e..d941ff529 100644 --- a/playfab-docs/multiplayer/servers/directly-debugging-game-servers.md +++ b/playfab-docs/multiplayer/servers/directly-debugging-game-servers.md @@ -52,7 +52,7 @@ This information is listed on __docker ps__: For more information, see [Docker networking](https://docs.docker.com/network/). > [!NOTE] -> In both Windows and Linux, Docker containers are part of the "playfab" Docker network. You can do docker inspect network playfab to see information about the network. +> In both Windows and Linux, Docker containers are part of the "playfab" Docker network. Use `docker inspect network playfab` to view information about the PlayFab network. #### How can I see runtime details for a container? diff --git a/playfab-docs/multiplayer/servers/os-patch-updates.md b/playfab-docs/multiplayer/servers/os-patch-updates.md index c2674de8d..3e0cef67e 100644 --- a/playfab-docs/multiplayer/servers/os-patch-updates.md +++ b/playfab-docs/multiplayer/servers/os-patch-updates.md @@ -12,11 +12,11 @@ ms.localizationpriority: medium # OS patch updates for Windows -Playfab Multiplayers Servers managed Windows containers undergo a methodical OS patch update process to ensure game servers are operating with the latest security updates. Each month, Azure Compute certifies a Windows OS image that is integrated into Multiplayer Servers for developers to choose from the "Windows Server Core Preview" toggle during the build creation process. Developers are encouraged to test their non-production game servers built with the "Windows Server Core Preview" option. +PlayFab Multiplayers Servers managed Windows containers undergo a methodical OS patch update process to ensure game servers are operating with the latest security updates. Each month, Azure Compute certifies a Windows OS image that is integrated into Multiplayer Servers for developers to choose from the "Windows Server Core Preview" toggle during the build creation process. Developers are encouraged to test their non-production game servers built with the "Windows Server Core Preview" option. ![Multiplayer - OS Patch Update UX](media/ospatchupdate_ux.png) -After 30 days, Multiplayer Servers will migrate the Windows Server Core Preview to the Windows Server Core image option - signaling a PlayFab approved OS image for production readiness. This process will repeat every 30 days, cycling an OS preview image to its mainline OS core image. If a game server built with OS core version that doesn’t match PlayFab’s OS core version, PlayFab will auto-update your game build server with the latest mainline OS core image. This process is applied automatically with no build changes required by the developer. +After 30 days, Multiplayer Servers will migrate the Windows Server Core Preview to the Windows Server Core image option - signaling a PlayFab approved OS image for production readiness. This process repeats every 30 days, cycling an OS preview image to its mainline OS core image. If a game server built with OS core version that doesn’t match PlayFab’s OS core version, PlayFab will auto-update your game build server with the latest mainline OS core image. This process is applied automatically with no build changes required by the developer. ## Patch update cycle @@ -27,24 +27,24 @@ The following image illustrates the OS patch level update cycle. | Stage | Stakeholder | Description | |---|---|---| -| 1 | Customer | Continuous integration & test process deploys production game builds with OS core and tests game builds with OS preview | +| 1 | Customer | Continuous integration and test process deploys production game builds with OS core and tests game builds with OS preview | | 2 | Azure | MPS validates new published Windows OS patch | | 3 | MPS | PlayFab replaces MPS OS preview with Windows OS patch | | 4 | MPS | PlayFab replaces MPS OS core with MPS OS preview 30-days prior | | 5 | MPS | PlayFab auto-updates game builds with OS Core | -## Best Practices +## Best practices 1. Developers are encouraged to create and test their non-production game server builds with the OS preview image option. -1. Developers with a mature build and continuous integration & deployment process should take into consideration that OS image updates cycle every 30 days +1. Developers with a mature build and continuous integration and deployment process should take into consideration that OS image updates cycle every 30 days ## Constraints 1. The patch update process occurs monthly -1. Developers cannot opt out of the monthly OS patch level updates -1. The patch update process is only applicable to Windows managed containers and does not apply to custom containers or Linux. +1. Developers can't opt out of the monthly OS patch level updates +1. The patch update process is only applicable to Windows managed containers and doesn't apply to custom containers or Linux. > [!NOTE] > -> - Game server builds are immutable once created. Therefore, developers cannot toggle between OS image preview and OS image core. -> - A game server operating in production will be auto-updated to the latest OS core image version if the version that the build was made is older than the latest. This will be applied automatically for any new multiplayer server allocation request only. +> - Game server builds are immutable once created. Therefore, developers can't toggle between OS image preview and OS image core. +> - A game server operating in production will be auto-updated to the latest OS core image version if the version that the build was made is older than the latest. This will be applied automatically for any new multiplayer server allocation request only. diff --git a/playfab-docs/multiplayer/servers/server-samples-resources.md b/playfab-docs/multiplayer/servers/server-samples-resources.md index 654322cde..e74a1b196 100644 --- a/playfab-docs/multiplayer/servers/server-samples-resources.md +++ b/playfab-docs/multiplayer/servers/server-samples-resources.md @@ -1,7 +1,7 @@ --- title: Multiplayer Servers samples and resources author: joannaleecy -description: Samples and resources for Azure PlayFab Multiplayer Game Servers. +description: Samples and resources for PlayFab Multiplayer Game Servers. ms.author: jenelleb ms.date: 04/01/2021 ms.topic: article diff --git a/playfab-docs/multiplayer/servers/server-sdks.md b/playfab-docs/multiplayer/servers/server-sdks.md index 4ff381a1b..499eeec78 100644 --- a/playfab-docs/multiplayer/servers/server-sdks.md +++ b/playfab-docs/multiplayer/servers/server-sdks.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Multiplayer Game Server SDKs +title: PlayFab Multiplayer Game Server SDKs author: joannaleecy -description: Learn about the SDKs for Azure PlayFab Multiplayer Game Servers. +description: Learn about the SDKs for PlayFab Multiplayer Game Servers. ms.author: jenelleb ms.date: 01/21/2021 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, networking, party, sdk, sample ms.localizationpriority: medium --- -# Azure Playfab Multiplayer Game Server SDKs +# PlayFab Multiplayer Game Server SDKs -This topic lists the different flavors of Azure PlayFab Multiplayer Game Server SDKs (GSDKs) we have today. +This topic lists the different flavors of PlayFab Multiplayer Game Server SDKs (GSDKs) we have today. ## Download links diff --git a/playfab-docs/multiplayer/servers/server-terms.md b/playfab-docs/multiplayer/servers/server-terms.md index 656c86097..ed5a38b2a 100644 --- a/playfab-docs/multiplayer/servers/server-terms.md +++ b/playfab-docs/multiplayer/servers/server-terms.md @@ -1,7 +1,7 @@ --- -title: Playfab Multiplayer Server terms +title: PlayFab Multiplayer Server terms author: joannaleecy -description: Playfab Multiplayer Server terms. +description: PlayFab Multiplayer Server terms. ms.author: jenelleb ms.date: 03/10/2021 ms.topic: article @@ -12,18 +12,18 @@ ms.localizationpriority: medium # Terminology -This topic explains the terms used for PlayFab Multiplayer Server. We understand that it can be confusing since the word server is used in multiple places. +This article explains the terms used for PlayFab Multiplayer Server. We understand that it can be confusing since the word server is used in multiple places. -The internal structure of the PlayFab Multiplayer Server and general relationship of the various components is also lightly covered here. For details, see [Basics of a PlayFab game server](basics-of-a-playFab-game-server.md). +The article also briefly covers the internal structure of the PlayFab Multiplayer Server and the general relationship of the various components. For more information, see [Basics of a PlayFab game server](basics-of-a-playFab-game-server.md). ## PlayFab Multiplayer Servers -PlayFab Multiplayer Servers can also be known as PlayFab virtual machines (VMs) and Servers. +PlayFab Multiplayer Servers are also known as PlayFab virtual machines (VMs) and Servers. -They are Azure VMs with PlayFab managed service functionalities. Added functionalities optimize them for use as multiplayer game servers. +They're Azure VMs with PlayFab managed service functionalities. The added functionalities optimize them for use as multiplayer game servers. Each PlayFab VM: -* Has a component known as *PlayFab VM agent*. PlayFab VM agent provides information about your game server's current state, health status, players that are currently connected, and other telemtry. +* Has a component known as *PlayFab VM agent*. PlayFab VM agent provides information about your game server's current state, health status, players that are currently connected, and other telemetry. * Can have multiple containers (game servers) running on them. Containers are a way to wrap up an application into its own isolated package. To learn more, see [What is a container?](https://azure.microsoft.com/overview/what-is-a-container/) ### Game server containers @@ -32,24 +32,24 @@ Game servers run as containerized applications. This means that your game server Each container: * Functions as a game server -* Has a PlayFab Multiplayer Game Server Build. It is your usual game server build that is integrated with the PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must include the GSDK and implement specific methods using APIs in the GSDK. This enables your game server to be connected to the PlayFab VM agent. +* Has a PlayFab Multiplayer Game Server Build. It is your usual game server build that is integrated with the PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must include the GSDK and implement specific methods using APIs in the GSDK. This integration enables your game server to connect to the PlayFab VM agent. -Image below illustrates the various components of a PlayFab Multiplayer Server. +The following image illustrates the various components of a PlayFab Multiplayer Server. ![PlayFab Multiplayer Server components](media/tutorials/multiplayer-server-hosting-service-diagram.png) ## Definition of key terms -* **Game server executable**: This is a game server application that runs in containers of PlayFab VMs. It may be a simple network repeater, a fully authoritative game server running physics and AI, or anything in between. All game server executables needs to be integrated with PlayFab Game Server SDK (GSDK). This allows your game server to be able to interact with the PlayFab Multiplayer platform service. +* **Game server executable**: This term refers to a game server application that runs in containers on PlayFab VMs. It might be a simple network repeater, a fully authoritative game server running physics and AI, or anything in between. All game server executables need to be integrated with PlayFab Game Server SDK (GSDK). By using this SDK, your game server can interact with the PlayFab Multiplayer platform service. -* **Game server build**: This is the full set of content that is uploaded onto the game server. It includes the game server executable packaged with all the assets and certificates needed. It can be uploaded as individual certificates, zip files, and/or a container image. If you don't need a custom container image, you can use PlayFab managed Windows containers. +* **Game server build**: This term refers to the full set of content that you upload onto the game server. It includes the game server executable packaged with all the assets and certificates needed. You can upload it as individual certificates, zip files, and/or a container image. If you don't need a custom container image, you can use PlayFab managed Windows containers. -* **PlayFab Multiplayer Game Server Build**: This is the only type of game server build that can be used in PlayFab Multiplayer Servers. It is your usual game server build (as defined above) that is integrated with the PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must include the GSDK and implement specific methods using APIs in the GSDK. +* **PlayFab Multiplayer Game Server Build**: This term refers to the only type of game server build that you can use in PlayFab Multiplayer Servers. It's your usual game server build (as defined above) that you integrate with the PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must include the GSDK and implement specific methods by using APIs in the GSDK. -* **Game server**: This is your game server executable running in a container. There may be multiple containers (servers) running on a single virtual machine. +* **Game server**: This term refers to your game server executable running in a container. A single virtual machine can run multiple containers (servers). * **PlayFab VM agent**: This agent is built into PlayFab VMs and facilitates key server interactions with the *PlayFab Multiplayer platform service*. The GSDK in the game server executable connects your game server to the PlayFab agent. -* **PlayFab Multiplayer platform service**: Managed service that runs in the background for PlayFab Multiplayer Servers. It communicates information through PlayFab VM agent about your game server's current state, health status, players that are currently connected, and other telemtry. +* **PlayFab Multiplayer platform service**: This managed service runs in the background for PlayFab Multiplayer Servers. It communicates information through the PlayFab VM agent about your game server's current state, health status, players that are currently connected, and other telemetry. ## Next steps diff --git a/playfab-docs/multiplayer/servers/vmstartupscript.md b/playfab-docs/multiplayer/servers/vmstartupscript.md index 5a7a2fa88..edd2a1d0f 100644 --- a/playfab-docs/multiplayer/servers/vmstartupscript.md +++ b/playfab-docs/multiplayer/servers/vmstartupscript.md @@ -17,7 +17,7 @@ ms.localizationpriority: medium > [!Important] > This feature is in preview. You're welcome to start using it today and give us your feedback. Instructions on how to connect with us is provided at the end of the article. Note that technical support is limited during preview. -VmStartupScript allows you to run a custom script on virtual machines (VMs) that are used in Azure PlayFab Multiplayer Servers (MPS). MPS is optimized for game servers hosting, making it easy for your title to scale dynamically according to demand. To improve the ease of customizing a large number of servers quickly during VM initialization, the custom script can run on every underlying VM that hosts your game servers. It can be used to accomplish tasks such as installing custom software, modifying security settings, using a custom service to log game server output and metrics, and more. +VmStartupScript allows you to run a custom script on virtual machines (VMs) that are used in PlayFab Multiplayer Servers (MPS). MPS is optimized for game servers hosting, making it easy for your title to scale dynamically according to demand. To improve the ease of customizing a large number of servers quickly during VM initialization, the custom script can run on every underlying VM that hosts your game servers. It can be used to accomplish tasks such as installing custom software, modifying security settings, using a custom service to log game server output and metrics, and more. > [!Note] > This is an advanced feature that should be used with extreme caution. The running script executes in the Virtual Machine (VM) level with admin (root) privileges. If not used properly, it can potentially disrupt the regular flow of the running game servers, or even prevent them from running at all. The end user is responsible for the content of the script. diff --git a/playfab-docs/player-progression/game-saves/offline.md b/playfab-docs/player-progression/game-saves/offline.md index c40c7417c..65a66f187 100644 --- a/playfab-docs/player-progression/game-saves/offline.md +++ b/playfab-docs/player-progression/game-saves/offline.md @@ -28,7 +28,7 @@ When network is unavailable or the user chooses to play offline, the system ente ### Handling Network Failures During Initial Sync -When `PFGameSaveFilesAddUserWithUiAsync()` is called without network connectivity, it triggers a `PFGameSaveFilesUiSyncFailedCallback`. Users can respond with two options: +When `PFGameSaveFilesAddUserWithUiAsync()` is called without network connectivity, it triggers a `PFGameSaveFilesUiSyncFailedCallback`. The `XAsyncBlock` callback doesn't fire while the system waits for the user's response—the async operation is paused until the user selects a terminal action. ```cpp // Handle sync failure callback @@ -48,8 +48,9 @@ void MyPFGameSaveFilesUiSyncFailedCallback(PFLocalUserHandle localUserHandle, PF ``` **User Response Options:** -- **Try Again**: Attempts the network call again (loops back to failure callback if still offline) -- **Use Offline**: `PFGameSaveFilesAddUserWithUiAsync` async callback reports `S_OK` but puts system into offline mode (can be detected with `PFGameSaveFilesIsConnectedToCloud()`) +- **Try Again (`Retry`)**: Retries the network call. If the retry also fails, this callback fires again and the user must respond again. The `XAsyncBlock` callback remains deferred through each retry loop. +- **Use Offline (`UseOffline`)**: The `XAsyncBlock` callback fires with `S_OK`, but the system enters offline mode (detectable with `PFGameSaveFilesIsConnectedToCloud()`). +- **Cancel**: The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. ### API Behavior in Offline Mode @@ -89,8 +90,12 @@ Use this API before attempting cloud operations to provide appropriate user feed ### Upload Behavior in Connected Mode -Even in connected mode, uploads can fail due to network issues. When this happens: -- Failure UI callback is triggered -- User can choose to retry or cancel -- If cancelled, async completion returns `E_PF_GAMESAVE_USER_CANCELLED` -- The game can call upload again later when network is restored +Even in connected mode, uploads can fail due to network issues or rate limits. When this happens, the `XAsyncBlock` callback doesn't fire immediately—the async operation pauses while the system waits for the user's response through the [UI callback state machine](./ui-callbacks.md#how-the-state-machine-works): + +1. The `PFGameSaveFilesUiSyncFailedCallback` fires with the error details. +2. The `XAsyncBlock` callback doesn't fire yet—the operation is paused while the system waits for a response. +3. If the user selects `Retry`, the upload retries. If it fails again, the callback fires again and the user must respond again. +4. If the user selects `Cancel`, the `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. +5. If a retry succeeds, the `XAsyncBlock` callback fires with `S_OK`. + +The game can call `PFGameSaveFilesUploadWithUiAsync()` again later when network is restored. diff --git a/playfab-docs/player-progression/game-saves/quickstart.md b/playfab-docs/player-progression/game-saves/quickstart.md index 187b07c92..48a8cb97e 100644 --- a/playfab-docs/player-progression/game-saves/quickstart.md +++ b/playfab-docs/player-progression/game-saves/quickstart.md @@ -298,47 +298,24 @@ If you aren't using the progress callback, wait for the `XAsyncBlock` to complet ## Step 4: Handle UI Callbacks (Optional) -Game Saves provides built-in UI for Xbox and Windows platforms, but you can customize the user experience by implementing your own UI callbacks. +Game Saves provides built-in UI for Xbox and Windows platforms. On other platforms (such as Steam Deck), your game must provide its own UI by handling callbacks. -### Platform Requirements -- **Xbox/Windows**: Built-in UI is provided; custom callbacks are optional -- **Other platforms** (Steam Deck, etc.): Custom UI callbacks are **required** - -### Types of UI Callbacks -- **Progress**: Show upload/download progress to users -- **Conflicts**: Handle situations where local and cloud saves differ -- **Active Device Contention**: Warn when user tries to sync on multiple devices -- **Sync Failures**: Handle network or other sync errors -- **Out of Storage**: Notify users when local storage is too full to sync - -### When Callbacks Trigger -UI callbacks only occur during two operations: -- `PFGameSaveFilesAddUserWithUiAsync` (download from cloud) -- `PFGameSaveFilesUploadWithUiAsync` (upload to cloud) - -### Implementation +UI callbacks fire during `PFGameSaveFilesAddUserWithUiAsync` and `PFGameSaveFilesUploadWithUiAsync`. Each callback pauses the async operation until your game responds—the `XAsyncBlock` callback doesn't fire until all UI callbacks are resolved. ```cpp // Set up custom UI callbacks (call this before AddUser or Upload operations) // See sample for detailed examples of these callbacks. -hr = PFGameSaveFilesSetUiCallbacks( - MyPFGameSaveFilesUiProgressCallback, nullptr, - MyPFGameSaveFilesUiSyncFailedCallback, nullptr, - MyPFGameSaveFilesUiActiveDeviceContentionCallback, nullptr, - MyPFGameSaveFilesUiConflictCallback, nullptr, - MyPFGameSaveFilesUiOutOfStorageCallback, nullptr); +PFGameSaveUICallbacks callbacks{}; +callbacks.progressCallback = MyProgressCallback; +callbacks.syncFailedCallback = MySyncFailedCallback; +callbacks.activeDeviceContentionCallback = MyActiveDeviceContentionCallback; +callbacks.conflictCallback = MyConflictCallback; +callbacks.outOfStorageCallback = MyOutOfStorageCallback; + +HRESULT hr = PFGameSaveFilesSetUiCallbacks(&callbacks); ``` -### Response APIs -Each callback has a corresponding response API: -- `PFGameSaveFilesSetUiProgressResponse()` - Respond to progress callback, letting users cancel -- `PFGameSaveFilesSetUiConflictResponse()` - Respond to conflict callbacks -- `PFGameSaveFilesSetUiActiveDeviceContentionResponse()` - Respond to device contention -- `PFGameSaveFilesSetUiSyncFailedResponse()` - Respond to sync failures -- `PFGameSaveFilesSetUiOutOfStorageResponse()` - Respond to local storage full issues - -> [!IMPORTANT] -> The Game Saves system waits for your response before continuing. Always call the appropriate response API when handling callbacks (except progress callbacks which don't need a response). +For the full list of callback types, response APIs, user actions, and details on how the state machine works, see [Game Saves UI callbacks](./ui-callbacks.md). ## Understanding Save Conflicts diff --git a/playfab-docs/player-progression/game-saves/toc.yml b/playfab-docs/player-progression/game-saves/toc.yml index 5b9f621b4..77d316fe7 100644 --- a/playfab-docs/player-progression/game-saves/toc.yml +++ b/playfab-docs/player-progression/game-saves/toc.yml @@ -12,6 +12,8 @@ items: href: steam-deck-implementation.md - name: Conflicts href: conflicts.md +- name: UI Callbacks + href: ui-callbacks.md - name: Offline Mode href: offline.md - name: Active Device Changes diff --git a/playfab-docs/player-progression/game-saves/ui-callbacks.md b/playfab-docs/player-progression/game-saves/ui-callbacks.md new file mode 100644 index 000000000..0579cba8a --- /dev/null +++ b/playfab-docs/player-progression/game-saves/ui-callbacks.md @@ -0,0 +1,175 @@ +--- +title: Game Saves UI callbacks +author: amccalib +description: How Game Saves UI callbacks work, including the state machine model, callback types, and response APIs. +ms.author: andmcc +ms.date: 03/06/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, game saves, ui callbacks, sync failed, conflict, progress +ms.localizationpriority: medium +--- + +# Game Saves UI callbacks + +Game Saves provides a set of UI callbacks that let your game respond to events during sync operations. On Xbox and Windows, the platform provides built-in UI for these events. On other platforms (such as Steam Deck), your game must implement its own UI by handling these callbacks. + +Setting callbacks on Xbox and Windows overrides the platform-provided UI with your implementation. This is useful if your game needs a consistent player experience across all platforms—register the same callbacks everywhere and the built-in UI won't appear. + +## How the state machine works + +Game Saves uses an internal state machine to coordinate UI callbacks with the async operation lifecycle. When a UI callback fires, the async operation pauses—the `XAsyncBlock` callback doesn't fire until the callback is resolved. The state machine doesn't progress until the game calls the corresponding response API or the async operation is canceled. + +This means: + +- Each callback type has a corresponding response API. Call the response API to tell the system what to do next. +- Response APIs can be called inside or outside the callback function. +- If a response action is `Retry`, the operation retries and may trigger the same callback again. +- The `XAsyncBlock` callback only fires once the operation reaches a terminal state—success, cancellation, or an offline fallback. + +For example, if an upload fails due to rate limits: + +1. `PFGameSaveFilesUiSyncFailedCallback` fires with the error. +2. The `XAsyncBlock` callback doesn't fire yet—the state machine waits for a response. +3. If the user selects `Retry` and the retry also fails, the sync failed callback fires again. +4. If the user selects `Cancel`, the `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. +5. If a retry succeeds, the `XAsyncBlock` callback fires with `S_OK`. + +## When callbacks trigger + +UI callbacks only fire during two async operations: + +| Operation | Callbacks that can trigger | +|-----------|--------------------------| +| `PFGameSaveFilesAddUserWithUiAsync` | Progress, Sync Failed, Active Device Contention, Conflict, Out of Storage | +| `PFGameSaveFilesUploadWithUiAsync` | Progress, Sync Failed | + +## Registering callbacks + +Register all callbacks before calling `PFGameSaveFilesAddUserWithUiAsync` or `PFGameSaveFilesUploadWithUiAsync`: + +```cpp +PFGameSaveUICallbacks callbacks{}; +callbacks.progressCallback = MyProgressCallback; +callbacks.progressContext = nullptr; +callbacks.syncFailedCallback = MySyncFailedCallback; +callbacks.syncFailedContext = nullptr; +callbacks.activeDeviceContentionCallback = MyActiveDeviceContentionCallback; +callbacks.activeDeviceContentionContext = nullptr; +callbacks.conflictCallback = MyConflictCallback; +callbacks.conflictContext = nullptr; +callbacks.outOfStorageCallback = MyOutOfStorageCallback; +callbacks.outOfStorageContext = nullptr; + +HRESULT hr = PFGameSaveFilesSetUiCallbacks(&callbacks); +``` + +## Callback reference + +### Progress + +Reports upload or download progress. Use `PFGameSaveFilesUiProgressGetProgress` inside the callback to retrieve the current `PFGameSaveFilesSyncState`, bytes completed, and bytes total. + +**Callback**: `PFGameSaveFilesUiProgressCallback` + +**Response API**: `PFGameSaveFilesSetUiProgressResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | + +> [!NOTE] +> The progress callback doesn't require a response to continue—the operation keeps progressing on its own. Only call the response API if the user wants to cancel. + +#### Sync states + +The `PFGameSaveFilesSyncState` enum indicates which phase the operation is in: + +| State | Description | Safe to write to save folder? | +|-------|-------------|-------------------------------| +| `NotStarted` | Operation hasn't begun | Yes | +| `PreparingForDownload` | Preparing to download from cloud | Yes | +| `Downloading` | Downloading from cloud | No | +| `PreparingForUpload` | Reading and compressing local files | No | +| `Uploading` | Upload to cloud in progress (local files captured) | Yes | +| `SyncComplete` | Operation finished | Yes | + +### Sync failed + +Fires when a sync operation fails, for example due to network issues or rate limits. + +**Callback**: `PFGameSaveFilesUiSyncFailedCallback` + +**Parameters**: Receives `PFGameSaveFilesSyncState` (the phase that failed) and `HRESULT` (the error code). + +**Response API**: `PFGameSaveFilesSetUiSyncFailedResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | +| `Retry` | Retries the failed operation. If the retry fails, this callback fires again. | +| `UseOffline` | Only valid during `PFGameSaveFilesAddUserWithUiAsync`. The `XAsyncBlock` callback fires with `S_OK`, but the system enters offline mode. Use `PFGameSaveFilesIsConnectedToCloud()` to detect this state. | + +For more details on offline mode behavior, see [Game Saves offline mode](./offline.md). + +### Active device contention + +Fires during `PFGameSaveFilesAddUserWithUiAsync` when another device is already the active device for this user. The callback receives `PFGameSaveDescriptor` structs for both the local and remote save data, which include device names, timestamps, and save sizes that you can display to help the user decide. + +**Callback**: `PFGameSaveFilesUiActiveDeviceContentionCallback` + +**Response API**: `PFGameSaveFilesSetUiActiveDeviceContentionResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | +| `Retry` | Retries—useful if the user expects the other device to release soon. If the other device is still active, this callback fires again. | +| `SyncLastSavedData` | Makes the local device active and syncs. The remote device can no longer upload and receives an active device changed notification. | + +For more details on active device behavior, see [Game Saves active device changes](./activedevicechanges.md). + +### Conflict + +Fires during `PFGameSaveFilesAddUserWithUiAsync` when local and cloud save data have diverged. The callback receives `PFGameSaveDescriptor` structs for both the local and remote save data. + +**Callback**: `PFGameSaveFilesUiConflictCallback` + +**Response API**: `PFGameSaveFilesSetUiConflictResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | +| `TakeLocal` | Keeps local save data and uploads it to the cloud. | +| `TakeRemote` | Discards local changes and downloads the cloud save data. | + +> [!IMPORTANT] +> Conflict resolution applies to the entire save, not individual files or folders. For details on how conflicts are detected at the atomic unit level and resolved globally, see [Game Saves conflicts](./conflicts.md). + +### Out of storage + +Fires during `PFGameSaveFilesAddUserWithUiAsync` when the local device doesn't have enough disk space to download save data from the cloud. The callback receives `requiredBytes` indicating how much space is needed. + +**Callback**: `PFGameSaveFilesUiOutOfStorageCallback` + +**Response API**: `PFGameSaveFilesSetUiOutOfStorageResponse` + +| Action | Effect | +|--------|--------| +| `Cancel` | Cancels the operation. The `XAsyncBlock` callback fires with `E_PF_GAMESAVE_USER_CANCELLED`. | +| `Retry` | Retries after the user frees local storage space. If there still isn't enough space, this callback fires again. | + +## Platform requirements + +| Platform | UI callbacks | +|----------|-------------| +| **Xbox and Windows** | Optional. Set callbacks to override the built-in UI. | +| **Other platforms** (Steam Deck, etc.) | **Required**. No built-in UI is available; your game must handle all callbacks. | + +For Steam Deck implementation details, see [Steam Deck implementation guide](./steam-deck-implementation.md). + +## Related content + +- [Game Saves quickstart](./quickstart.md) +- [Game Saves offline mode](./offline.md) +- [Game Saves conflicts](./conflicts.md) +- [Game Saves active device changes](./activedevicechanges.md) diff --git a/playfab-docs/player-progression/index.yml b/playfab-docs/player-progression/index.yml index 5034e95fb..ec0692dd9 100644 --- a/playfab-docs/player-progression/index.yml +++ b/playfab-docs/player-progression/index.yml @@ -1,6 +1,6 @@ ### YamlMime:Landing -title: Azure PlayFab Player progression documentation +title: PlayFab Player progression documentation summary: PlayFab Player Progression services enable reliable storage and sharing of player progression data across all gaming devices. # < 160 chars metadata: diff --git a/playfab-docs/player-progression/statistics/index.md b/playfab-docs/player-progression/statistics/index.md index e7058074a..c2efbd05f 100644 --- a/playfab-docs/player-progression/statistics/index.md +++ b/playfab-docs/player-progression/statistics/index.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab Statistics overview +title: PlayFab Statistics overview author: braulioal -description: Learn about Azure PlayFab Statistics. +description: Learn about PlayFab Statistics. ms.author: braulioal ms.date: 09/01/2024 ms.topic: article @@ -10,9 +10,9 @@ keywords: playfab, multiplayer, leaderboard, stats ms.localizationpriority: medium --- -# Azure PlayFab Statistics overview +# PlayFab Statistics overview -Azure Playfab Statistics is a cross-platform service that enables the numerical representation of player activity within a title. +PlayFab Statistics is a cross-platform service that enables the numerical representation of player activity within a title. ![PlayFab Stats Architecture](media/stats-relationship.png) diff --git a/playfab-docs/pricing/Meters/meters.md b/playfab-docs/pricing/Meters/meters.md index 9487c24c7..63afe42a9 100644 --- a/playfab-docs/pricing/Meters/meters.md +++ b/playfab-docs/pricing/Meters/meters.md @@ -122,7 +122,7 @@ PlayFab Matchmaking and Lobby are highly-customizable, proven solutions for buil ### Leaderboard -Azure Playfab Leaderboards is a cross-platform service that allows to create a sorted list of players with the purpose +PlayFab Leaderboards is a cross-platform service that allows to create a sorted list of players with the purpose of ranking them by scores. * **[Leaderboard Reads](leaderboard-meters.md)**: Metered by API calls that read from Leaderboards. @@ -131,7 +131,7 @@ of ranking them by scores. ### Statistics -Azure Playfab Statistics is a cross-platform service that allows to track the activity of players within the game. +PlayFab Statistics is a cross-platform service that allows to track the activity of players within the game. * **[Statistics Reads](statistics-meters.md)**: Metered by API calls that read from Statistics. * **[Statistics Writes](statistics-meters.md)**: Metered by API calls that write to Statistics. diff --git a/playfab-docs/pricing/Meters/profile-reads.md b/playfab-docs/pricing/Meters/profile-reads.md index a0ddb336b..c1c804464 100644 --- a/playfab-docs/pricing/Meters/profile-reads.md +++ b/playfab-docs/pricing/Meters/profile-reads.md @@ -10,11 +10,11 @@ keywords: playfab, pricing ms.localizationpriority: medium --- -# Profile Reads +# Profile reads Profile includes any data stored related to the player profile, entity profile, character profile, groups, and inventory. Profile data is information that applies to an individual player, group of players, or items, and is stored as Key/Value Pairs (KVPs) by PlayFab. -The following APIs cause the Profile read meter to increment. +The following APIs increment the profile read meter. ## Admin APIs @@ -22,7 +22,7 @@ The following APIs cause the Profile read meter to increment. Checks the global count for the limited edition item. - [GetAllSegments](/rest/api/playfab/admin/play-stream/get-all-segments?view=playfab-rest&preserve-view=true) - Retrieves an array of player segment definitions. Results from this can be used in subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names can change the ID for that segment will not change. + Retrieves an array of player segment definitions. Results from this can be used in subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names can change the ID for that segment won't change. - [ExportMasterPlayerData](/rest/api/playfab/admin/account-management/export-master-player-data?view=playfab-rest&preserve-view=true) Exports all associated data of a master player account. @@ -31,16 +31,16 @@ The following APIs cause the Profile read meter to increment. Retrieves the specified version of the title's catalog of virtual goods, including all defined properties. - [GetContentList](/rest/api/playfab/admin/content/get-content-list?view=playfab-rest&preserve-view=true) - List all contents of the title and get statistics such as size. + Lists all contents of the title and gets statistics such as size. - [GetDataReport](/rest/api/playfab/admin/player-data-management/get-data-report?view=playfab-rest&preserve-view=true) Retrieves a download URL for the requested report. - [GetPlayerSegments](/rest/api/playfab/admin/play-stream/get-player-segments?view=playfab-rest&preserve-view=true) - List all segments that a player currently belongs to at this moment in time. + Lists all segments that a player currently belongs to at this moment in time. - [GetPlayerTags](/rest/api/playfab/admin/play-stream/get-player-tags?view=playfab-rest&preserve-view=true) - Get all tags with a given Namespace (optional) from a player profile. + Gets all tags with a given Namespace (optional) from a player profile. - [GetPolicy](/rest/api/playfab/admin/authentication/get-policy?view=playfab-rest&preserve-view=true) Gets the requested policy. @@ -55,7 +55,7 @@ The following APIs cause the Profile read meter to increment. Retrieves the set of items defined for the specified store, including all prices defined. - [GetTitleData](/rest/api/playfab/admin/title-wide-data-management/get-title-data?view=playfab-rest&preserve-view=true) - Retrieves the key-value store of custom title settings which can be read by the client. + Retrieves the key-value store of custom title settings that can be read by the client. - [GetUserAccountInfo](Retrieves the relevant details for a specified user, based upon a match against a supplied unique identifier) Retrieves the relevant details for a specified user, based upon a match against a supplied unique identifier. @@ -64,34 +64,34 @@ The following APIs cause the Profile read meter to increment. Gets all bans for a user. - [GetUserData](/rest/api/playfab/admin/player-data-management/get-user-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which is readable and writable by the client. + Retrieves the title-specific custom data for the user that's readable and writable by the client. - [GetUserInternalData](/rest/api/playfab/admin/player-data-management/get-user-internal-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which cannot be accessed by the client. + Retrieves the title-specific custom data for the user, which can't be accessed by the client. - [GetUserInventory](/rest/api/playfab/admin/player-item-management/get-user-inventory?view=playfab-rest&preserve-view=true) Retrieves the specified user's current inventory of virtual goods - [GetUserPublisherData](/rest/api/playfab/admin/player-data-management/get-user-publisher-data?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which is readable and writable by the client. + Retrieves the publisher-specific custom data for the user that's readable and writable by the client. - [GetUserPublisherInternalData](/rest/api/playfab/admin/player-data-management/get-user-publisher-internal-data?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which cannot be accessed by the client. + Retrieves the publisher-specific custom data for the user that can't be accessed by the client. - [GetUserPublisherReadOnlyData](/rest/api/playfab/admin/player-data-management/get-user-publisher-read-only-data?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which can only be read by the client. + Retrieves the publisher-specific custom data for the user that can only be read by the client. - [GetUserReadOnlyData](/rest/api/playfab/admin/player-data-management/get-user-read-only-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which can only be read by the client. + Retrieves the title-specific custom data for the user that can only be read by the client. - [ListVirtualCurrencyTypes](/rest/api/playfab/admin/title-wide-data-management/list-virtual-currency-types?view=playfab-rest&preserve-view=true) - Retuns the list of all defined virtual currencies for the title + Returns the list of all defined virtual currencies for the title - [GetPlayerIdFromAuthToken](/rest/api/playfab/admin/account-management/get-player-id-from-auth-token?view=playfab-rest&preserve-view=true) Gets a player's ID from an auth token. - [GetPlayersInSegment](/rest/api/playfab/admin/play-stream/get-players-in-segment?view=playfab-rest&preserve-view=true) - Allows for paging through all players in a given segment. This API creates a snapshot of all player profiles that match the segment definition at the time of its creation and lives through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation Token. Profiles that change during the course of paging will not be reflected in the results. AB Test segments are currently not supported by this operation. + Allows for paging through all players in a given segment. This API creates a snapshot of all player profiles that match the segment definition at the time of its creation and lives through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation Token. Profiles that change during paging won't be reflected in the results. AB Test segments are currently not supported by this operation. - [GetExperiments](/rest/api/playfab/experimentation/experimentation/get-experiments?view=playfab-rest&preserve-view=true) Gets the details of all experiments for a title. @@ -105,13 +105,13 @@ The following APIs cause the Profile read meter to increment. ## Client APIs - [GetAllUsersCharacters](/rest/api/playfab/client/characters/get-all-users-characters?view=playfab-rest&preserve-view=true) - Lists all of the characters that belong to a specific user. CharacterIds are not globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness. + Lists all of the characters that belong to a specific user. CharacterIds aren't globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness. - [GetCatalogItems](/rest/api/playfab/client/title-wide-data-management/get-catalog-items?view=playfab-rest&preserve-view=true) Retrieves the specified version of the title's catalog of virtual goods, including all defined properties. - [GetCharacterData](/rest/api/playfab/client/character-data/get-character-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the character which is readable and writable by the client. + Retrieves the title-specific custom data for the character that's readable and writable by the client. - [GetCharacterInventory](/rest/api/playfab/client/player-item-management/get-character-inventory?view=playfab-rest&preserve-view=true) Retrieves the specified character's current inventory of virtual goods. @@ -120,7 +120,7 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of ranked characters for the given statistic, starting from the indicated point in the leaderboard. - [GetCharacterReadOnlyData](/rest/api/playfab/client/character-data/get-character-read-only-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the character which can only be read by the client. + Retrieves the title-specific custom data for the character that can only be read by the client. - [GetCharacterStatistics](/rest/api/playfab/client/characters/get-character-statistics?view=playfab-rest&preserve-view=true) Retrieves the details of all title-specific statistics for the user. @@ -132,7 +132,7 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of ranked friends of the current player for the given statistic, centered on the requested PlayFab user. If PlayFabId is empty or null will return currently logged in user. - [GetFriendsList](/rest/api/playfab/client/friend-list-management/get-friends-list?view=playfab-rest&preserve-view=true) - Retrieves the current friend list for the local user, constrained to users who have PlayFab accounts. Friends from linked accounts (Facebook, Steam) are also included. You may optionally exclude some linked services' friends. + Retrieves the current friend list for the local user, constrained to users who have PlayFab accounts. Friends from linked accounts (Facebook, Steam) are also included. You can optionally exclude some linked services' friends. - [GetLeaderboard](/rest/api/playfab/client/player-data-management/get-leaderboard?view=playfab-rest&preserve-view=true) Retrieves a list of ranked users for the given statistic, starting from the indicated point in the leaderboard. @@ -147,13 +147,13 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of all of the user's characters for the given statistic. - [GetPaymentToken](/rest/api/playfab/client/player-item-management/get-payment-token?view=playfab-rest&preserve-view=true) - For payments flows where the provider requires playfab (the fulfiller) to initiate the transaction, but the client completes the rest of the flow. In the Xsolla case, the token returned here will be passed to Xsolla by the client to create a cart. Poll GetPurchase using the returned OrderId once you've completed the payment. + For payment flows where the provider requires PlayFab (the fulfiller) to initiate the transaction, but the client completes the rest of the flow. In the Xsolla case, the token returned here will be passed to Xsolla by the client to create a cart. Poll GetPurchase using the returned OrderId once you've completed the payment. - [GetPlayerProfile](/rest/api/playfab/client/account-management/get-player-profile?view=playfab-rest&preserve-view=true) Retrieves the player's profile. - [GetPlayerSegments](/rest/api/playfab/client/play-stream/get-player-segments?view=playfab-rest&preserve-view=true) - List all segments that a player currently belongs to at this moment in time. + Lists all segments that a player currently belongs to at this moment in time. - [GetPlayerStatistics](/rest/api/playfab/client/player-data-management/get-player-statistics?view=playfab-rest&preserve-view=true) Retrieves the indicated statistics (current version and values for all statistics, if none are specified), for the local player. @@ -162,10 +162,10 @@ The following APIs cause the Profile read meter to increment. Retrieves the information on the available versions of the specified statistic. - [GetPlayerTags](/rest/api/playfab/client/play-stream/get-player-tags?view=playfab-rest&preserve-view=true) - Get all tags with a given Namespace (optional) from a player profile. + Gets all tags with a given Namespace (optional) from a player profile. - [GetPlayerTrades](/rest/api/playfab/client/trading/get-player-trades?view=playfab-rest&preserve-view=true) - Gets all trades the player has either opened or accepted, optionally filtered by trade status. + Gets all trades the player either opens or accepts, optionally filtered by trade status. - [GetPlayFabIDsFromFacebookIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-facebook-ids?view=playfab-rest&preserve-view=true) Retrieves the unique PlayFab identifiers for the given set of Facebook identifiers. @@ -180,16 +180,16 @@ The following APIs cause the Profile read meter to increment. Retrieves the unique PlayFab identifiers for the given set of generic service identifiers. A generic identifier is the service name plus the service-specific ID for the player, as specified by the title when the generic identifier was added to the player account. - [GetPlayFabIDsFromGoogleIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-google-ids?view=playfab-rest&preserve-view=true) - Retrieves the unique PlayFab identifiers for the given set of Google identifiers. The Google identifiers are the IDs for the user accounts, available as "id" in the Google+ People API calls. + Retrieves the unique PlayFab identifiers for the given set of Google identifiers. The Google identifiers are the IDs for the user accounts, available as `id` in the Google+ People API calls. - [GetPlayFabIDsFromKongregateIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-kongregate-ids?view=playfab-rest&preserve-view=true) - Retrieves the unique PlayFab identifiers for the given set of Kongregate identifiers. The Kongregate identifiers are the IDs for the user accounts, available as "user_id" from the Kongregate API methods(ex: http://developers.kongregate.com/docs/client/getUserId). + Retrieves the unique PlayFab identifiers for the given set of Kongregate identifiers. The Kongregate identifiers are the IDs for the user accounts, available as `user_id` from the Kongregate API methods(for example, https://docs.kongregate.com/docs/concepts-handling-guests). - [GetPlayFabIDsFromNintendoSwitchDeviceIds](/rest/api/playfab/client/account-management/get-playfab-ids-from-nintendo-switch-device-ids?view=playfab-rest&preserve-view=true) Retrieves the unique PlayFab identifiers for the given set of Nintendo Switch identifiers. - [GetPlayFabIDsFromPSNAccountIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-psn-account-ids?view=playfab-rest&preserve-view=true) - Retrieves the unique PlayFab identifiers for the given set of PlayStation™Network identifiers. + Retrieves the unique PlayFab identifiers for the given set of PlayStation™ Network identifiers. - [GetPlayFabIDsFromSteamIDs](/rest/api/playfab/client/account-management/get-playfab-ids-from-steam-ids?view=playfab-rest&preserve-view=true) Retrieves the unique PlayFab identifiers for the given set of Steam identifiers. The Steam identifiers are the profile IDs for the user accounts, available as SteamId in the Steamworks Community API calls. @@ -207,7 +207,7 @@ The following APIs cause the Profile read meter to increment. Retrieves a purchase along with its current PlayFab status. Returns inventory items from the purchase that are still active. - [GetSharedGroupData](/rest/api/playfab/client/shared-group-data/get-shared-group-data?view=playfab-rest&preserve-view=true) - Retrieves data stored in a shared group object, as well as the list of members in the group. Non-members of the group may use this to retrieve group data, including membership, but they will not receive data for keys marked as private. Shared Groups are designed for sharing data between a very small number of players, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). + Retrieves data stored in a shared group object, and the list of members in the group. Non-members of the group use this to retrieve group data, including membership, but they won't receive data for keys marked as private. Shared Groups are designed for sharing data between a small number of players. For more information, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). - [GetStoreItems](/rest/api/playfab/client/title-wide-data-management/get-store-items?view=playfab-rest&preserve-view=true) Retrieves the set of items defined for the specified store, including all prices defined. @@ -219,51 +219,51 @@ The following APIs cause the Profile read meter to increment. Retrieves the user's PlayFab account details. - [LoginWithAndroidDeviceID](/rest/api/playfab/client/authentication/login-with-android-device-id?view=playfab-rest&preserve-view=true) - Signs the user in using the Android device identifier, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using the Android device identifier, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithCustomID](/rest/api/playfab/client/authentication/loginwithcustomid?view=playfab-rest&preserve-view=true) - Signs the user in using a custom unique identifier generated by the title, returning a session identifier that can subsequently be used for API calls which require an authenticated user + Signs the user in using a custom unique identifier generated by the title, returning a session identifier that can later be used for API calls that require an authenticated user - [LoginWithEmailAddress](/rest/api/playfab/client/authentication/login-with-email-address?view=playfab-rest&preserve-view=true) - Signs the user into the PlayFab account, returning a session identifier that can subsequently be used for API calls which require an authenticated user. Unlike most other login API calls, LoginWithEmailAddress does not permit the creation of new accounts via the CreateAccountFlag. Email addresses may be used to create accounts via RegisterPlayFabUser. + Signs the user into the PlayFab account, returning a session identifier that can later be used for API calls that require an authenticated user. Unlike most other login API calls, LoginWithEmailAddress doesn't permit the creation of new accounts via the CreateAccountFlag. Email addresses can be used to create accounts via RegisterPlayFabUser. - [LoginWithFacebook](/rest/api/playfab/client/authentication/login-with-facebook?view=playfab-rest&preserve-view=true) - Signs the user in using a Facebook access token, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using a Facebook access token, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithFacebookInstantGamesId](/rest/api/playfab/client/authentication/login-with-facebook-instant-games-id?view=playfab-rest&preserve-view=true) - Signs the user in using a Facebook Instant Games ID, returning a session identifier that can subsequently be used for API calls which require an authenticated user. Requires Facebook Instant Games to be configured. + Signs the user in using a Facebook Instant Games ID, returning a session identifier that can then be used for API calls that require an authenticated user. Requires Facebook Instant Games to be configured. - [LoginWithGameCenter](/rest/api/playfab/client/authentication/loginwithgamecenter?view=playfab-rest&preserve-view=true) - Signs the user in using an iOS Game Center player identifier, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an iOS Game Center player identifier, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithGoogleAccount](/rest/api/playfab/client/authentication/login-with-game-center?view=playfab-rest&preserve-view=true) - Signs the user in using an iOS Game Center player identifier, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an iOS Game Center player identifier, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithIOSDeviceID](/rest/api/playfab/client/authentication/login-with-google-account?view=playfab-rest&preserve-view=true) - Signs the user in using their Google account credentials. + Signs the user in by using their Google account credentials. - [LoginWithKongregate](/rest/api/playfab/client/authentication/login-with-kongregate?view=playfab-rest&preserve-view=true) - Signs the user in using a Kongregate player account. + Signs the user in by using a Kongregate player account. - [LoginWithNintendoSwitchDeviceId](/rest/api/playfab/client/authentication/login-with-nintendo-switch-device-id?view=playfab-rest&preserve-view=true) - Signs the user in using a Nintendo Switch Device ID, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using a Nintendo Switch Device ID, returning a session identifier that can then be used for API calls that require an authenticated user. - [LoginWithOpenIdConnect](/rest/api/playfab/client/authentication/login-with-openid-connect?view=playfab-rest&preserve-view=true) - Logs in a user with an Open ID Connect JWT created by an existing relationship between a title and an Open ID Connect provider. + Logs in a user by using an Open ID Connect JWT created by an existing relationship between a title and an Open ID Connect provider. - [LoginWithPlayFab](/rest/api/playfab/client/authentication/login-with-playfab?view=playfab-rest&preserve-view=true) - which require an authenticated user. Unlike most other login API calls, LoginWithPlayFab does not permit the creation of new accounts via the CreateAccountFlag. Username/Password credentials may be used to create accounts via RegisterPlayFabUser, or added to existing accounts using AddUsernamePassword. + which require an authenticated user. Unlike most other login API calls, `LoginWithPlayFab` doesn't permit the creation of new accounts via the `CreateAccountFlag`. Username/Password credentials can be used to create accounts via `RegisterPlayFabUser`, or added to existing accounts using `AddUsernamePassword`. -- [LoginWithPSN](/rest/api/playfab/client/authentication/login-with-psn?view=playfab-rest&preserve-view=true) Signs the user into the PlayFab account, returning a session identifier that can subsequently be used for API calls which require an authenticated user. Unlike most other login API calls, LoginWithPlayFab does not permit the creation of new accounts via the CreateAccountFlag. Username/Password credentials may be used to create accounts via RegisterPlayFabUser, or added to existing accounts using AddUsernamePassword. +- [LoginWithPSN](/rest/api/playfab/client/authentication/login-with-psn?view=playfab-rest&preserve-view=true) Signs the user into the PlayFab account, returning a session identifier that can then be used for API calls that require an authenticated user. Unlike most other login API calls, `LoginWithPlayFab` doesn't permit the creation of new accounts via the `CreateAccountFlag`. Username/Password credentials are used to create accounts via `RegisterPlayFabUser`, or added to existing accounts using `AddUsernamePassword`. - [LoginWithSteam](/rest/api/playfab/client/authentication/login-with-steam?view=playfab-rest&preserve-view=true) - Signs the user in using a Steam authentication ticket, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using a Steam authentication ticket, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithTwitch](/rest/api/playfab/client/authentication/login-with-twitch?view=playfab-rest&preserve-view=true) - Signs the user in using a Twitch access token. + Signs the user in by using a Twitch access token. - [LoginWithXbox](/rest/api/playfab/client/authentication/loginwithxbox?view=playfab-rest&preserve-view=true) - Signs the user in using a Xbox Live Token, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an Xbox Live Token, returning a session identifier that can later be used for API calls that require an authenticated user. - [GetPlayerCombinedInfo](/rest/api/playfab/client/account-management/get-player-combined-info?view=playfab-rest&preserve-view=true) Retrieves all of the user's different kinds of info. @@ -281,7 +281,7 @@ The following APIs cause the Profile read meter to increment. Gets information about a group and its roles. - [IsMember](/rest/api/playfab/groups/groups/is-member?view=playfab-rest&preserve-view=true) - Checks to see if an entity is a member of a group or role within the group. + Checks if an entity is a member of a group or role within the group. - [ListGroupApplications](/rest/api/playfab/groups/groups/list-group-applications?view=playfab-rest&preserve-view=true) Lists all outstanding requests to join a group. @@ -318,22 +318,22 @@ The following APIs cause the Profile read meter to increment. ## Server APIs - [EvaluateRandomResultTable](/rest/api/playfab/server/player-item-management/evaluate-random-result-table?view=playfab-rest&preserve-view=true) - Returns the result of an evaluation of a Random Result Table - the ItemId from the game Catalog which would have been added to the player inventory, if the Random Result Table were added via a Bundle or a call to UnlockContainer. + Returns the result of an evaluation of a Random Result Table - the `ItemId` from the game Catalog that would have been added to the player inventory, if the Random Result Table were added via a Bundle or a call to UnlockContainer. - [GetAllSegments](/rest/api/playfab/server/play-stream/get-all-segments?view=playfab-rest&preserve-view=true) - Retrieves an array of player segment definitions. Results from this can be used in subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names can change the ID for that segment will not change. + Retrieves an array of player segment definitions. Results from this can be used in subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names can change the ID for that segment won't change. - [GetAllUsersCharacters](/rest/api/playfab/server/characters/get-all-users-characters?view=playfab-rest&preserve-view=true) - Lists all of the characters that belong to a specific user. CharacterIds are not globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness. + Lists all of the characters that belong to a specific user. CharacterIds aren't globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness. - [GetCatalogItems](/rest/api/playfab/server/title-wide-data-management/get-catalog-items?view=playfab-rest&preserve-view=true) Retrieves the specified version of the title's catalog of virtual goods, including all defined properties. - [GetCharacterData](/rest/api/playfab/server/character-data/get-character-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which is readable and writable by the client. + Retrieves the title-specific custom data for the user that's readable and writable by the client. - [GetCharacterInternalData](/rest/api/playfab/server/character-data/get-character-internal-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user's character which cannot be accessed by the client. + Retrieves the title-specific custom data for the user's character that can't be accessed by the client. - [GetCharacterInventory](/rest/api/playfab/server/player-item-management/get-character-inventory?view=playfab-rest&preserve-view=true) Retrieves the specified character's current inventory of virtual goods. @@ -347,7 +347,7 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of ranked friends of the given player for the given statistic, starting from the indicated point in the leaderboard. - [GetFriendsList](/rest/api/playfab/server/friend-list-management/get-friends-list?view=playfab-rest&preserve-view=true) - Retrieves the current friends for the user with PlayFabId, constrained to users who have PlayFab accounts. Friends from linked accounts (Facebook, Steam) are also included. You may optionally exclude some linked services' friends. + Retrieves the current friends for the user with `PlayFabId`, constrained to users who have PlayFab accounts. Friends from linked accounts (Facebook, Steam) are also included. You might optionally exclude some linked services' friends. - [GetLeaderboard](/rest/api/playfab/server/player-data-management/get-leaderboard?view=playfab-rest&preserve-view=true) Retrieves a list of ranked users for the given statistic, starting from the indicated point in the leaderboard. @@ -362,16 +362,16 @@ The following APIs cause the Profile read meter to increment. Retrieves a list of all of the user's characters for the given statistic. - [GetPlayerCombinedInfo](/rest/api/playfab/server/player-data-management/get-player-combined-info?view=playfab-rest&preserve-view=true) - Returns whatever info is requested in the response for the user. Note that PII (like email address, facebook id) may be returned. All parameters default to false. + Returns whatever info is requested in the response for the user. Note that personal date, like email address, facebook ID, might be returned. All parameters default to false. - [GetPlayerProfile](/rest/api/playfab/server/account-management/get-player-profile?view=playfab-rest&preserve-view=true) Retrieves the player's profile. - [GetPlayerSegments](/rest/api/playfab/server/play-stream/get-player-segments?view=playfab-rest&preserve-view=true) - List all segments that a player currently belongs to at this moment in time. + Lists all segments that a player currently belongs to at this moment in time. - [GetPlayersInSegment](/rest/api/playfab/server/play-stream/get-players-in-segment?view=playfab-rest&preserve-view=true) - Allows for paging through all players in a given segment. This API creates a snapshot of all player profiles that match the segment definition at the time of its creation and lives through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation Token. Profiles that change during the course of paging will not be reflected in the results. AB Test segments are currently not supported by this operation. + Allows for paging through all players in a given segment. This API creates a snapshot of all player profiles that match the segment definition at the time of its creation and lives through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation Token. Profiles that change during paging aren't reflected in the results. AB Test segments are currently not supported by this operation. - [GetPlayerStatistics](/rest/api/playfab/server/player-data-management/get-player-statistics?view=playfab-rest&preserve-view=true) Retrieves the current version and values for the indicated statistics, for the local player. @@ -380,7 +380,7 @@ The following APIs cause the Profile read meter to increment. Retrieves the information on the available versions of the specified statistic. - [GetPlayerTags](/rest/api/playfab/server/play-stream/get-player-tags?view=playfab-rest&preserve-view=true) - Get all tags with a given Namespace (optional) from a player profile. + Gets all tags with a given Namespace (optional) from a player profile. - [GetPlayFabIDsFromFacebookIDs](/rest/api/playfab/server/account-management/getplayfabidsfromfacebookids?view=playfab-rest&preserve-view=true) Retrieves the unique PlayFab identifiers for the given set of Facebook identifiers. @@ -413,7 +413,7 @@ The following APIs cause the Profile read meter to increment. Retrieves the associated PlayFab account identifiers for the given set of server custom identifiers. - [GetSharedGroupData](/rest/api/playfab/server/shared-group-data/get-shared-group-data?view=playfab-rest&preserve-view=true) - Retrieves data stored in a shared group object, as well as the list of members in the group. The server can access all public and private group data. Shared Groups are designed for sharing data between a very small number of players, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). + Retrieves data stored in a shared group object, and the list of members in the group. The server can access all public and private group data. Shared Groups are designed for sharing data between a small number of players. For more information, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). - [GetStoreItems](/rest/api/playfab/server/title-wide-data-management/get-store-items?view=playfab-rest&preserve-view=true) Retrieves the set of items defined for the specified store, including all prices defined, for the specified player. @@ -431,30 +431,30 @@ The following APIs cause the Profile read meter to increment. Gets all bans for a user. - [GetUserData](/rest/api/playfab/server/player-data-management/get-user-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which is readable and writable by the client. + Retrieves the title-specific custom data for the user that is readable and writable by the client. - [GetUserInternalData](/rest/api/playfab/server/player-data-management/get-user-internal-data?view=playfab-rest&preserve-view=true) - Retrieves the title-specific custom data for the user which cannot be accessed by the client. + Retrieves the title-specific custom data for the user that can't be accessed by the client. - [GetUserInventory](/rest/api/playfab/server/player-item-management/get-user-inventory?view=playfab-rest&preserve-view=true) Retrieves the specified user's current inventory of virtual goods. - [GetUserPublisherData](/rest/api/playfab/server/player-data-management/get-user-publisher-data?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which is readable and writable by the client. + Retrieves the publisher-specific custom data for the user that is readable and writable by the client. - [GetUserPublisherInternalData](/rest/api/playfab/server/player-data-management/getuserpublisherinternaldata?view=playfab-rest&preserve-view=true) - Retrieves the publisher-specific custom data for the user which cannot be accessed by the client. + Retrieves the publisher-specific custom data for the user that can't be accessed by the client. - [GetUserPublisherReadOnlyData](/rest/api/playfab/server/player-data-management/get-user-publisher-internal-data?view=playfab-rest&preserve-view=true) - [GetUserReadOnlyData](/rest/api/playfab/server/player-data-management/update-user-read-only-data?view=playfab-rest&preserve-view=true) - Updates the title-specific custom data for the user which can only be read by the client. + Updates the title-specific custom data for the user that can only be read by the client. - [LoginWithServerCustomId](/rest/api/playfab/server/authentication/login-with-server-custom-id?view=playfab-rest&preserve-view=true) - Securely login a game client from an external server backend using a custom identifier for that player. Server Custom ID and Client Custom ID are mutually exclusive and cannot be used to retrieve the same player account. + Securely login a game client from an external server backend using a custom identifier for that player. Server Custom ID and Client Custom ID are mutually exclusive and can't be used to retrieve the same player account. - [LoginWithXbox](/rest/api/playfab/server/authentication/login-with-xbox?view=playfab-rest&preserve-view=true) - Signs the user in using a Xbox Live Token from an external server backend, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an Xbox Live Token from an external server backend, returning a session identifier that can later be used for API calls that require an authenticated user. - [LoginWithXboxId](/rest/api/playfab/server/authentication/login-with-xbox-id?view=playfab-rest&preserve-view=true) - Signs the user in using an Xbox ID and Sandbox ID, returning a session identifier that can subsequently be used for API calls which require an authenticated user. + Signs the user in using an Xbox ID and Sandbox ID, returning a session identifier that can later be used for API calls that require an authenticated user. diff --git a/playfab-docs/pricing/Meters/profile-writes.md b/playfab-docs/pricing/Meters/profile-writes.md index aa0fae355..0ffc81b93 100644 --- a/playfab-docs/pricing/Meters/profile-writes.md +++ b/playfab-docs/pricing/Meters/profile-writes.md @@ -175,7 +175,7 @@ The following APIs cause the Profile writes meter to increment. Adds users to the set of those able to update both the shared data, as well as the set of users in the group. Only users in the group (and the server) can add new members. Shared Groups are designed for sharing data between a very small number of players, see [Using Shared Group Data](../../community/associations/groups/using-shared-group-data.md). - [AddUsernamePassword](/rest/api/playfab/client/account-management/addusernamepassword?) - Adds playfab username/password auth to an existing account created via an anonymous auth method, e.g. automatic device ID login. + Adds PlayFab username/password auth to an existing account created via an anonymous auth method, e.g. automatic device ID login. - [AndroidDevicePushNotificationRegistration](/rest/api/playfab/client/platform-specific-methods/androiddevicepushnotificationregistration?) Registers the Android device to receive push notifications @@ -247,7 +247,7 @@ The following APIs cause the Profile writes meter to increment. Registers the iOS device to receive push notifications - [RegisterPlayFabUser](/rest/api/playfab/client/authentication/registerplayfabuser?) - Registers a new Playfab user account, returning a session identifier that can subsequently be used for API calls which require an authenticated user. You must supply either a username or an email address. + Registers a new PlayFab user account, returning a session identifier that can subsequently be used for API calls which require an authenticated user. You must supply either a username or an email address. - [RemoveContactEmail](/rest/api/playfab/client/account-management/removecontactemail?) Removes a contact email from the player's profile. diff --git a/playfab-docs/release-notes/2025.md b/playfab-docs/release-notes/2025.md new file mode 100644 index 000000000..5f34b3bfc --- /dev/null +++ b/playfab-docs/release-notes/2025.md @@ -0,0 +1,226 @@ +--- +title: PlayFab Services SDK Release Notes 2025 +author: stevenLizano29 +description: PlayFab Services SDK Release Notes for 2025. +ms.author: v-stevenroj +ms.date: 03/09/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, development, release, apis, features +ms.localizationpriority: medium +--- +# PlayFab Services SDK Release Notes 2025 + +> [!NOTE] +> For release notes about service releases and product updates, see the [release notes](https://github.com/PlayFab/PlayFab/releases) section on [PlayFab's public GitHub repository](https://github.com/PlayFab/PlayFab) + +## 251219 + +Date: December 19, 2025 + + - Added StartDate field to Economy API + - Added error codes for new service errors + +## 251205 + +Date: December 5, 2025 + + - Added GetPlayFabIDsFromOpenIdSubjectIdentifiers to the Client and Server APIs + - Added the following calls to the Server API: + - LinkTwitchAccount + - LoginWithTwitch + - UnlinkTwitchAccount + - Added error codes for new service errors + +## 251121 + +Date: November 21, 2025 + + - Added MarketplaceConfigurationName to the Economy API + - Updated RestrictInvitesToLobbyOwner in the Multiplayer API + - Added error codes for new service errors + +## 251107 + +Date: November 7, 2025 + + - Added PageSize and SkipToken pagination fields to multiple calls in the Progression API + - Added JwsReceiptData type to the Economy API + - Added error codes for new service errors + +## 251024 + +Date: October 24, 2025 + + - Added AlternateIdType and AlternateIdValue fields to the Economy API + - Added error codes for new service errors + +## 251010 + +Date: October 10, 2025 + + - Added error codes for new service errors + +## 250926 + +Date: September 26, 2025 + + - Added RedeemAppleAppStoreWithJwsInventoryItems to the Economy API for Apple App Store JWS receipt validation + - Added error codes for new service errors + +## 250912 + +Date: September 12, 2025 + + - Added UnlinkAggregationSourceFromStatistic to the Progression API + - Added LinkXboxId to the Server API + - Added time range query types for store metrics in the Admin API + - Added error codes for new service errors + +## 250815 + +Date: August 15, 2025 + + - Added LeaderboardVersionEndConfig, LeaderboardEventEmissionConfig, and StatisticsEventEmissionConfig types to the Progression API + - Added pricing override types to the Economy API + - Added Apple and Xbox add-on configuration fields to the Addon API + - Added error codes for new service errors + +## 250801 + +Date: August 1, 2025 + + - Added GetStoreMetrics to the Admin API + - Added error codes for new service errors + +## 250718 + +Date: July 18, 2025 + + - Added CustomTags to GetTransactionHistory in the Economy API + - Added FunctionResultSize field to the CloudScript API + - Added error codes for new service errors + +## 250704 + +Date: July 4, 2025 + + - Added ContinuationToken and Count fields to the Economy API + - Added error codes for new service errors + +## 250620 + +Date: June 20, 2025 + + - Added VersionedCatalogsSource field to the Economy API + - Added error codes for new service errors + +## 250606 + +Date: June 6, 2025 + + - Added clawback tracking fields to transaction history in the Economy API (TransactionClawbackDetails) + - Added StatisticNames filter to GetEntityStatistics in the Progression API + - Added error codes for new service errors + +## 250526 + +Date: May 26, 2025 + + - Added the following calls to the Addon API for ToxMod management: + - CreateOrUpdateToxMod + - DeleteToxMod + - GetToxMod + - Renamed LinkBattleNet to LinkBattleNetAccount and UnlinkBattleNet to UnlinkBattleNetAccount in the Client API + - Added ExportVersionedCatalog to the Economy API. Removed UploadVersionedCatalog. + - Added the following Data Connection management calls to the Events API: + - DeleteDataConnection + - GetDataConnection + - ListDataConnections + - SetDataConnection + - SetDataConnectionActive + - Added the following calls to the Server API: + - LinkBattleNetAccount + - LoginWithBattleNet + - UnlinkBattleNetAccount + - Expanded Economy API catalog items with real-money price details across multiple storefronts + - Added error codes for new service errors + +## 250425 + +Date: April 25, 2025 + + - Added Battle.net identity provider support with the following calls to the Client API: + - GetPlayFabIDsFromBattleNetAccountIds + - LinkBattleNet + - LoginWithBattleNet + - UnlinkBattleNet + - Added GetPlayFabIDsFromBattleNetAccountIds to the Server API + - Added the following login calls to the Server API: + - LoginWithAndroidDeviceID + - LoginWithCustomID + - LoginWithIOSDeviceID + - Added the following calls to the Economy API: + - CompleteVersionedCatalogUpload + - CreateVersionedCatalogUploadURL + - GetVersionedCatalogUploadStatus + - Added the following TrueSkill calls to the Multiplayer API: + - GetPlayerSkillForConditions + - GetPlayerSkillForConditionsFromModel + - Added error codes for new service errors + +## 250328 + +Date: March 28, 2025 + + - Added DeleteVersionedCatalog to the Economy API + - Added RestrictInvitesToLobbyOwner to the Multiplayer API + - Added error codes for new service errors + +## 250314 + +Date: March 14, 2025 + + - Added the following calls to the Economy API: + - GetVersionedCatalogItem + - UploadVersionedCatalog + - Added TrueSkill-related types to the Multiplayer API + - Added error codes for new service errors + +## 250228 + +Date: February 28, 2025 + + - Cleaned up API spec schema formatting across all APIs. No functional API changes. + +## 250214 + +Date: February 14, 2025 + + - Removed the following deprecated calls from the Economy API: + - Inventory/AddVirtualCurrencies + - Inventory/ConsumeInventoryItems + - Catalog/EvaluateDropTable + - Inventory/GetAccessTokens + - Inventory/GetReceiptIssuerCertificateAsJwk + - Inventory/GetReceiptIssuerCertificateAsPem + - Inventory/GetVirtualCurrencies + - Inventory/GrantInventoryItems + - Catalog/PurchaseItemByFriendlyId + - Catalog/PurchaseItemById + - Inventory/Redeem + - Inventory/RefreshSubscriptions + - Inventory/SetInventoryItems + - Inventory/SetVirtualCurrencies + - Inventory/SubtractVirtualCurrencies + - Inventory/UpdateInventoryItemsProperties + - Added UpdateLeaderboardDefinition and UpdateStatisticDefinition to the Progression API + - Added NextReset field to leaderboard definitions in the Progression API + - Added error codes for new service errors + +## 250117 + +Date: January 17, 2025 + + - Added error codes for new service errors + - Added TransactionId to UpdateStatisticsRequest in the Progression API \ No newline at end of file diff --git a/playfab-docs/release-notes/index.md b/playfab-docs/release-notes/index.md index 478ad6e70..a1da27b06 100644 --- a/playfab-docs/release-notes/index.md +++ b/playfab-docs/release-notes/index.md @@ -1,22 +1,46 @@ --- -title: PlayFab Services SDK Release Notes 2025 -author: amccalib -description: PlayFab Services SDK Release Notes for 2025. -ms.author: andmcc -ms.date: 01/28/2025 +title: PlayFab Services SDK Release Notes 2026 +author: stevenLizano29 +description: PlayFab Services SDK Release Notes for 2026. +ms.author: v-stevenroj +ms.date: 03/09/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, development, release, apis, features ms.localizationpriority: medium --- -# PlayFab Services SDK Release Notes 2025 +# PlayFab Services SDK Release Notes 2026 > [!NOTE] > For release notes about service releases and product updates, see the [release notes](https://github.com/PlayFab/PlayFab/releases) section on [PlayFab's public GitHub repository](https://github.com/PlayFab/PlayFab) -## 250117 +## 260227 -Date: January 17, 2025 +Date: February 27, 2026 + - Added ProductDisabledForTitle error code to multiple calls across the Client, Server, and Admin APIs + - Added error codes for new service errors + +## 260213 + +Date: February 13, 2026 + + - Added AddOrUpdateContactEmail to the Server API + - Added PubSub connection lifetime extension support to the Multiplayer API + - Added error codes for new service errors + +## 260123 + +Date: January 23, 2026 + + - Removed GetMicrosoftStoreAccessTokens from the Economy API + - Added error codes for new service errors + +## 260109 + +Date: January 9, 2026 + + - Added the following calls to the Server API: + - UnlinkFacebookAccount + - UnlinkFacebookInstantGamesId - Added error codes for new service errors - - Added TransactionId to UpdateStatisticsRequest in the Progression API \ No newline at end of file diff --git a/playfab-docs/release-notes/toc.yml b/playfab-docs/release-notes/toc.yml index f889885f0..e42d3ab68 100644 --- a/playfab-docs/release-notes/toc.yml +++ b/playfab-docs/release-notes/toc.yml @@ -1,5 +1,7 @@ -- name: 2025 SDK Release Notes +- name: 2026 SDK Release Notes href: ./index.md +- name: 2025 SDK Release Notes + href: ./2025.md - name: 2024 SDK Release Notes href: ./2024.md - name: 2023 SDK Release Notes diff --git a/playfab-docs/sdks/c-sharp/index.md b/playfab-docs/sdks/c-sharp/index.md index 12319eeaf..1734e8737 100644 --- a/playfab-docs/sdks/c-sharp/index.md +++ b/playfab-docs/sdks/c-sharp/index.md @@ -39,7 +39,7 @@ The C# PlayFab SDK shouldn't be used if there's a more specific SDK that is suit Specific PlayFab SDK is available for: * [Unity PlayFab SDK GitHub repo](https://github.com/PlayFab/UnitySDK) -For a full list of the different PlayFab SDKs, see [Azure PlayFab SDK](../playfab-sdk-intro.md). +For a full list of the different PlayFab SDKs, see [PlayFab SDK](../playfab-sdk-intro.md). ## Using the SDK diff --git a/playfab-docs/sdks/c/index.md b/playfab-docs/sdks/c/index.md index 7611116bb..23f4a01fd 100644 --- a/playfab-docs/sdks/c/index.md +++ b/playfab-docs/sdks/c/index.md @@ -48,8 +48,8 @@ Here are some notable differences when compared to other, more general purpose, ## Benefits of this SDK -- Allows titles to control the memory allocations when calling Playfab Services. See [Managing Memory Allocations](memory.md) to learn more. -- Allows titles to gain full control of thread handling when calling Playfab Services. See [Making async calls in the PlayFab Services SDK](async.md) to learn more. +- Allows titles to control the memory allocations when calling PlayFab Services. See [Managing Memory Allocations](memory.md) to learn more. +- Allows titles to gain full control of thread handling when calling PlayFab Services. See [Making async calls in the PlayFab Services SDK](async.md) to learn more. - Portable C interface that allows maximum compatibility across platforms, compilers, and languages. - High-performance telemetry pipeline with support for low-cost queuing and batch transmission of events. diff --git a/playfab-docs/sdks/playfab-sdk-intro.md b/playfab-docs/sdks/playfab-sdk-intro.md index ececa5ede..7a4fb679f 100644 --- a/playfab-docs/sdks/playfab-sdk-intro.md +++ b/playfab-docs/sdks/playfab-sdk-intro.md @@ -1,7 +1,7 @@ --- -title: Azure PlayFab SDKs +title: PlayFab SDKs author: joannaleecy -description: Azure PlayFab SDKs +description: PlayFab SDKs ms.author: jenelleb ms.date: 03/04/2024 ms.topic: article @@ -27,7 +27,7 @@ For broad API categories in these SDKs, see [API REST operation groups](/rest/ap | Language | Platform/environments | |-----------------------------------|-------------------------------------------| -| C/C++ | [Windows (Win32), iOS, MacOS, Android, Linux](c/index.md), [GDK (Xbox and Windows)](c/index.md), [Switch](https://dev.azure.com/PlayFabPrivate/Switch/_git/PlayFabCSdk.Switch), [PlayStation 4](https://dev.azure.com/PlayFabPrivate/PS4/_git/PlayFabCSdk.PS4), [PlayStation 5](https://dev.azure.com/PlayFabPrivate/PS5/_git/PlayFabCSdk.PS5) | +| C/C++ | [Windows (Win32), iOS, macOS, Android, Linux](c/index.md), [GDK (Xbox and Windows)](c/index.md), [Switch](https://dev.azure.com/PlayFabPrivate/Switch/_git/PlayFabCSdk.Switch), [PlayStation 4](https://dev.azure.com/PlayFabPrivate/PS4/_git/PlayFabCSdk.PS4), [PlayStation 5](https://dev.azure.com/PlayFabPrivate/PS5/_git/PlayFabCSdk.PS5) | | Legacy C++ | [Windows (Win32), iOS, Android, Linux](playfab-cpp/index.md), [Switch](https://dev.azure.com/PlayFabPrivate/Switch/_git/XPlatCppSdk-Private-Switch), [PlayStation 4](https://dev.azure.com/PlayFabPrivate/PS4/_git/XPlatCppSdk-Private-Ps4), [PlayStation 5](https://dev.azure.com/PlayFabPrivate/PS5/_git/XPlatCppSdk-Private-PS5) | | C# | [C#/.NET environments](c-sharp/index.md) besides Unity | | Java | [Android apps](java/index.md) | diff --git a/playfab-docs/whats-new/toc.yml b/playfab-docs/whats-new/toc.yml index 016339489..a735f94d7 100644 --- a/playfab-docs/whats-new/toc.yml +++ b/playfab-docs/whats-new/toc.yml @@ -3,8 +3,10 @@ items: ## href: whats-new.md - name: Previous Release Notes items: - - name: 2025 SDK Release Notes + - name: 2026 SDK Release Notes href: /playfab-docs/release-notes/index.md + - name: 2025 SDK Release Notes + href: /playfab-docs/release-notes/2025.md - name: Lobby and Matchmaking SDK Release Notes href: ../multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md - name: PlayFab Party SDK Release Notes From b7da74f068f4f8ac0856cd8118fba0d5d91266b3 Mon Sep 17 00:00:00 2001 From: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:05:50 -0500 Subject: [PATCH 70/76] [DO NOT MERGE UNTIL MARCH 11] Foundation mode preview docs (#2842) * Audit on how we use "namespace" vs "studio" * Updates to development mode pages to reflect reduction in lifetime unique user limit * Cleans up URLs, removes language codes, and all login steps point to developer.playfab.com * First draft of mode overview and onboarding * Update playfab-docs/get-started/concepts.md * Update playfab-docs/get-started/concepts.md * Update playfab-docs/get-started/foundation-onboarding.md * Update playfab-docs/get-started/foundation-onboarding.md * Update playfab-docs/live-service-management/game-configuration/experiments/pricing.md * Update playfab-docs/pricing/development-mode.md * Update playfab-docs/pricing/development-mode.md * Fixes build warnings and suggestions * Unifies the casing on Development Mode * Addresses minor grammatical and styling errors * Fix Acrolinx issues in billingDetails.md and insights/pricing.md Address grammar, tense, contraction, punctuation, and clarity suggestions flagged by Acrolinx to improve scores above 80. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --- .../leaderboards/leaderboards-cloudscript.md | 2 +- .../leaderboards/quota-leaderboards.md | 2 +- .../legacy/insights/performance-retention.md | 2 +- .../data-analytics/legacy/insights/pricing.md | 14 +-- playfab-docs/get-started/concepts.md | 4 +- .../get-started/foundation-onboarding.md | 73 +++++++++++++ playfab-docs/get-started/mode-overview.md | 101 ++++++++++++++++++ .../game-configuration/experiments/pricing.md | 6 +- .../statistics/quota-statistics.md | 2 +- playfab-docs/pricing/account-upgrades.md | 29 +++-- playfab-docs/pricing/billingDetails.md | 26 ++--- .../pricing/consumption-best-practices.md | 22 ++-- playfab-docs/pricing/development-mode.md | 37 ++++--- playfab-docs/pricing/pricing-overview.md | 2 +- playfab-docs/pricing/title-launches.md | 29 ++--- 15 files changed, 257 insertions(+), 94 deletions(-) create mode 100644 playfab-docs/get-started/foundation-onboarding.md create mode 100644 playfab-docs/get-started/mode-overview.md diff --git a/playfab-docs/community/leaderboards/leaderboards-cloudscript.md b/playfab-docs/community/leaderboards/leaderboards-cloudscript.md index 8021d97c3..3bae2b510 100644 --- a/playfab-docs/community/leaderboards/leaderboards-cloudscript.md +++ b/playfab-docs/community/leaderboards/leaderboards-cloudscript.md @@ -19,7 +19,7 @@ By defining leaderboard-related logic within an Azure Function, your client can ## Prerequisites To follow this tutorial, you need: -- A PlayFab account. If you don't have one, you can create it [here](https://playfab.com/). +- A PlayFab account. If you don't have one, you can create it [here](https://developer.playfab.com/). - An Azure subscription. If you don't have one, you can create it [here](https://azure.microsoft.com/free/). For more details on how to create an Azure Function check this guide. [Create your first function in Azure using Visual Studio](https://learn.microsoft.com/azure/azure-functions/functions-create-your-first-function-visual-studio) diff --git a/playfab-docs/community/leaderboards/quota-leaderboards.md b/playfab-docs/community/leaderboards/quota-leaderboards.md index a235b679c..bdd894bb4 100644 --- a/playfab-docs/community/leaderboards/quota-leaderboards.md +++ b/playfab-docs/community/leaderboards/quota-leaderboards.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Quota limits leaderboards The Leaderboard service is designed to align with PlayFab's pricing models, offering two distinct modes: -development and live. The development mode allows titles to test each feature and begin development. +development and live. The Development Mode allows titles to test each feature and begin development. The live mode, on the other hand, is optimized for handling larger traffic loads typical of a live game. The following tables outline the limits for each of these modes: diff --git a/playfab-docs/data-analytics/legacy/insights/performance-retention.md b/playfab-docs/data-analytics/legacy/insights/performance-retention.md index 4804cff0c..904102d2d 100644 --- a/playfab-docs/data-analytics/legacy/insights/performance-retention.md +++ b/playfab-docs/data-analytics/legacy/insights/performance-retention.md @@ -31,7 +31,7 @@ The **Performance Level** slider is used to select a new performance level. The ### Is performance level access limited? Yes. Every title begins at Performance Level 1, a free tier of service that is included in all PlayFab offerings. Live titles can change their performance level at will, however, titles in Development Mode must either enable paid insights features or launch to access performance levels greater than 1. -To enable paid Insights features while a title is in development mode: +To enable paid Insights features while a title is in Development Mode: 1. Sign in to [developer.playfab.com](https://developer.playfab.com) 2. Select a title in Development Mode to enter the Title Overview page diff --git a/playfab-docs/data-analytics/legacy/insights/pricing.md b/playfab-docs/data-analytics/legacy/insights/pricing.md index a2e7a435b..485fa16c2 100644 --- a/playfab-docs/data-analytics/legacy/insights/pricing.md +++ b/playfab-docs/data-analytics/legacy/insights/pricing.md @@ -13,18 +13,18 @@ ms.localizationpriority: medium # Insights pricing > [!NOTE] -> PlayFab Insights Management was deprecated on December 11th, 2023. We recommend using [Azure Data Explorer (ADX) Connections](../../export-data/data-connection-adx.md) to manage your performance and cost going forward. If your title is still using **Insights**, continue to see this article for pricing details. For more information, see [Insights Deprecation Blog](https://developer.microsoft.com/en-us/games/articles/2023/09/playfab-insights-management-to-be-deprecated-starting-december-11/). +> PlayFab Insights Management was deprecated on December 11, 2023. We recommend using [Azure Data Explorer (ADX) Connections](../../export-data/data-connection-adx.md) to manage your performance and cost going forward. If your title is still using **Insights**, continue to see this article for pricing details. For more information, see [Insights Deprecation Blog](https://developer.microsoft.com/en-us/games/articles/2023/09/playfab-insights-management-to-be-deprecated-starting-december-11/). -The total combined usage of Insights features are billed in a virtual currency called "Insights Credits". Insight Credits are derived from conversion rates for usage of each Insight services. +The total combined usage of Insights features is billed in a virtual currency called "Insights Credits." Insight Credits are derived from conversion rates for usage of each Insight services. -The Standard and Premium pricing plans include a number of free monthly Insights credits. If usage exceeds the number of free credits, any additional credits are billed at the rate specified on your plan. The Pay-as-you-go pricing plan does not include free credits, so each credit is billed at the rate specified in the plan. For more information on the number of free credits and additional credit rates included in each plan, see [PlayFab pricing](http://playfab.com/pricing). +The Standard and Premium pricing plans include a number of free monthly Insights credits. If usage exceeds the number of free credits, any extra credits are billed at the rate specified on your plan. The Pay-as-you-go pricing plan doesn't include free credits, so each credit is billed at the rate specified in the plan. For more information on the number of free credits and additional credit rates included in each plan, see [PlayFab pricing](http://playfab.com/pricing). ## Insights Performance Each title is set to a chosen performance level that is billed to the minute (Insights Credits Per Hour / 60). The cost in credits for each performance level is located at the bottom of the table on the Insights Management page: ![Insights Slider](media/performance-level2.png) > [!IMPORTANT] -> All MAU-based pricing plans will be converted to a usage-based pricing plan on 11/01/2020. As part of the transition, a small number of titles will be placed on a paid Insights Performance level to maintain their current functionality. However, if a title would like to reduce the performance level (and thus cost) while also accepting a decrease in performance, the performance level can be adjusted on the Insights Management page in Game Manager using the above table. +> All MAU-based pricing plans will be converted to a usage-based pricing plan on November 1, 2020. As part of the transition, a few titles will be placed on a paid Insights Performance level to maintain their current functionality. However, if a title would like to reduce the performance level (and thus cost) while also accepting a decrease in performance, the performance level can be adjusted on the Insights Management page in Game Manager using the above table. ## Retention @@ -32,12 +32,12 @@ Data retention is billed in Terabyte months. Every day the end of day storage si ## Pricing example -Below is an example scenario illustrating how one month of Insights billing is calculated for a studio: +The following is an example scenario illustrating how one month of Insights billing is calculated for a studio: In April, a studio used performance level 4 from 9AM to 5PM each weekday and scaled down to performance level 2 at nights and on weekends. April has 21 weekdays and 9 weekend days, which works out to: * 21 days at performance level 4, for 8 hours * 21 days at performance level 2, for 16 hours -* 9 days at performance level 2, for 24 hours +* Nine days at performance level 2, for 24 hours The credit rate per hour for each of these levels is: * performance level 2 = 1 credits/hour @@ -54,4 +54,4 @@ Starting the month with no stored data, the studio added 1 TB of data every othe Thus, the studio's total monthly cost for Insights performance and data retention is 1,974 credits. ## Row Write Overages -Each Insights Performance level has an allotted number of writes per second to the data cluster. For customers not in development mode, going beyond the number of row writes for your performance level triggers row write overages instead of event throttling. Row write overages are charged at 1 credit per 2.7 million (2,700,000) rows written. This pricing is designed to allow for specific ingestion scenarios where it may be more cost effective to have row write overages instead of raising the Insights performance level. +Each Insights Performance level has an allotted number of writes per second to the data cluster. For customers not in Development Mode, going beyond the number of row writes for your performance level triggers row write overages instead of event throttling. Row write overages are charged at one credit per 2.7 million (2,700,000) rows written. This pricing is designed to allow for specific ingestion scenarios where it may be more cost effective to have row write overages instead of raising the Insights performance level. diff --git a/playfab-docs/get-started/concepts.md b/playfab-docs/get-started/concepts.md index b61097719..5263ba022 100644 --- a/playfab-docs/get-started/concepts.md +++ b/playfab-docs/get-started/concepts.md @@ -18,7 +18,7 @@ PlayFab offers various fundamental components that serve as the building blocks PlayFab uses a hierarchical structure to manage resources and configurations across different scopes. -A PlayFab namespace is the highest level entity that stores all of your global information. In the [PlayFab developer portal](../live-service-management/gamemanager/index.md), the namespace is referred to as the "Studio." +A PlayFab namespace is the highest-level entity that stores all global information which spans multiple titles. A PlayFab title is an entity that represents the data and configurations scoped to a specific game including game settings, player account, player data, and other game-related data. @@ -26,7 +26,7 @@ A namespace might contain many titles, but a title can only belong to one namesp All titles under the same namespace can share certain resources and configurations. This feature is useful for managing [player identities](../identity/identity-overview.md) and data across multiple titles within the same namespace. -Titles can also be used to store data and configuration specific to a game environment, a specific version of your game, or game-specific scoped. For example, you might want to have a title for your development environment, your testing environment, your certification environment, and your live environment to keep all your data and configurations cleanly separated. You might also want a separate title for special releases of your game such as play tests, open betas, or demos. +Titles can also be used to store data and configuration specific to a game environment or a version of your game. The purpose of a title is to manage game-specific data and configurations. Namespaces and titles are two specific types of entities with hierarchical relationships, and there are more [built-in entity types](../live-service-management/game-configuration/entities/available-built-in-entity-types.md) to represent other useful scopes such as players, groups, and servers. diff --git a/playfab-docs/get-started/foundation-onboarding.md b/playfab-docs/get-started/foundation-onboarding.md new file mode 100644 index 000000000..9b8f0ab05 --- /dev/null +++ b/playfab-docs/get-started/foundation-onboarding.md @@ -0,0 +1,73 @@ +--- +title: Foundation Mode Onboarding +author: m-kdearnley +description: Describes how to get started with Foundation Mode. +ms.author: kdearnley +ms.date: 02/13/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, pricing, free tier +ms.localizationpriority: medium +--- + +# Onboarding to Foundation Mode + +This article shows you how to set up Foundation Mode for your game. You'll request access to the preview, create a title in Foundation Mode, and link your Partner Center account. + +## Prerequisites + +Before you begin, make sure you have: + +- A [PlayFab developer account](../identity/dev-identity/pfab-account.md) +- A game that you're shipping or planning to ship on Xbox +- A [Partner Center account](https://developer.microsoft.com/en-GB/games/publish) (or create one during this process) + +## Request access to the preview + +> [!IMPORTANT] +> During the preview, Foundation Mode is available for **new titles only**. You can't migrate existing titles at this time. A migration path for existing titles is planned, targeting June 2026. + +During the preview period, you need to request access before you can create titles in Foundation Mode. + +1. Sign in to [Game Manager](https://developer.playfab.com/). +1. Navigate to your studio settings and select the Preview Features tab. You must have admin privileges for this tab to be visible. Studio settings can be reached from the home screen, click on the three dots (...) menu on your studio. +1. Select  **Foundation Mode** and complete the request form. +1. Wait for approval. You will receive an email when your studio is enabled for Foundation Mode. + +## Create a Partner Center account + +If you don't already have a Partner Center account, create one to use Foundation Mode. + +1. Go to the [Xbox developer onboarding hub](https://developer.microsoft.com/en-GB/games/publish). +1. Follow the steps to create your developer account. +1. Complete the account verification process. + + +## Create a title in Foundation Mode + +If your studio is onboarded to the Foundation Mode Preview, you can create new titles in Foundation Mode. + +1. Sign in to [Game Manager](https://developer.playfab.com/). +1. Select your studio. +1. Select **New Title**. +1. Enter a name and select the correct studio for your title. +1. Link your new PlayFab Title to an existing Seller ID and Product ID in Partner Center. These fields automatically populate based on the Microsoft Entra ID used to sign in to PlayFab. +1. Select **Create Title**. + +Your new title is now set up in Foundation Mode with access to all included features. + +## Support during preview + +If you encounter any issues, [file a support ticket](../pricing/support.md#support-ticket-submission). + +## Next steps + +Now that you are set up in Foundation Mode, start building your game: + +- [Set up player authentication](../identity/player-identity/authentication/index.md) +- [Configure multiplayer services](../multiplayer/index.yml) +- [Set up leaderboards](../community/leaderboards/index.md) + +## See also + +- [Foundation Mode overview](mode-overview.md) diff --git a/playfab-docs/get-started/mode-overview.md b/playfab-docs/get-started/mode-overview.md new file mode 100644 index 000000000..10a2c6f59 --- /dev/null +++ b/playfab-docs/get-started/mode-overview.md @@ -0,0 +1,101 @@ +--- +title: PlayFab Modes +author: m-kdearnley +description: Describes Foundation Mode, Development Mode. +ms.author: kdearnley +ms.date: 02/13/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, pricing, free tier +ms.localizationpriority: medium +--- + +# Foundation Mode overview + +Foundation Mode is a PlayFab service tier that enables eligible Xbox ecosystem developers to use PlayFab game services at no extra cost. It includes core features for player identity, multiplayer, progression, economy, and community - everything you need to build and ship games everywhere. + +If you're a developer shipping games on Xbox, or if you're planning to ship on Xbox, Foundation Mode gives you access to essential backend services without the stress of budgeting or billing. + +For more information about PlayFab's full capabilities, see [What is PlayFab?]( ../get-started/what-is-playfab.md). + +## Eligibility + +Developers are eligible for Foundation Mode if they meet the following requirements: + +- Register a studio in PlayFab Game Manager. + +- Ship or plan to ship their game on Xbox. + +- Link their PlayFab account to their Partner Center studio and product. + +> [!IMPORTANT] +> During the preview, Foundation Mode is available for **new PlayFab titles only**. You can create new titles in Foundation Mode, but existing titles cannot be migrated at this time. A migration path for existing titles is planned for mid-2026. + +## What's included + +Foundation Mode includes the following PlayFab features: + +**Identity** + +| **Feature** | **Description** | +|---|---| +| [Player Identity]( ../identity/player-identity/login/index.md) | Authenticate players and link accounts to enable cross-play and cross-progression features | +| [Server identity](/rest/api/playfab/authentication/authentication/authenticate-game-server-with-custom-id) | Authenticate game servers for secure backend communication | + +**Live service management** + +| **Feature** | **Description** | +|---|---| +| [API access policy]( ../api-references/api-access-policy.md) | Control access to PlayFab APIs for your title | +| [Title communications]( ../live-service-management/game-configuration/title-communications/overview.md) | Send targeted messages and notifications to players | +| [Title data]( ../live-service-management/game-configuration/titledata/index.md) | Store and retrieve title-level configuration data | + +**Game data stream** + +| **Feature** | **Description** | +|---|---| +| [Telemetry]( ../data-analytics/ingest-data/telemetry-overview.md) | Service-generated telemetry data (custom events excluded) | + +**Multiplayer** + + +| **Feature** | **Description** | +|---|---| +| [Lobby]( ../multiplayer/lobby/index.md) | Create and manage game lobbies for players | +| [Matchmaking]( ../multiplayer/matchmaking/index.md) | Match players based on skill, latency, and custom rules | +| [Party Networking]( ../multiplayer/networking/index.md) | Secure, low-latency networking for multiplayer games | +| [Real-time messages]( ../multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md) | Real-time messages from Lobby and Matchmaking services | + +**Community** + +| **Feature** | **Description** | +|---|---| +| [Friends]( ../community/associations/friends/index.md) | Manage player friend lists and relationships | +| [Groups]( ../community/associations/groups/index.md) | Create and manage player groups and guilds | +| [Player bans]( ../player-progression/player-data/player-bans.md) | Enforce community standards with player bans | +| [Leaderboards]( ../community/leaderboards/index.md) | Display player rankings and competition results | + +**Progression** + +| **Feature** | **Description** | +|---|---| +| [Player profile]( ../player-progression/player-data/index.md) | Store and retrieve player profile data | +| [Statistics]( ../player-progression/statistics/index.md) | Track player statistics and achievements | +| [Game saves]( ../player-progression/game-saves/overview.md) | Cloud save support for player progress | + +**Economy** + +| **Feature** | **Description** | +|---|---| +| [Catalog]( ../economy-monetization/economy-v2/catalog/catalog-overview.md) | Define and manage your game's virtual items | +| [Inventory](../economy-monetization/economy-v2/inventory/index.md) | Track player-owned items and currencies | + +## Service limits + +Foundation Mode includes API rate limits to ensure fair resource allocation, but there are no monthly caps on usage for Foundation Mode titles. Most rate limits are applied per-API-per-player; this restricts the number of calls a single player can make to a specific API endpoint in a short time period (For example, 30 calls per 2 minutes). This means that any experience that works at a developer's desk should accurately reflect how the game operates at scale, regardless of how many players your live game has. + +View all limits for your title in Game Manager under Settings > Limits. + +## See also + +- [Foundation Mode Onboarding](foundation-onboarding.md) \ No newline at end of file diff --git a/playfab-docs/live-service-management/game-configuration/experiments/pricing.md b/playfab-docs/live-service-management/game-configuration/experiments/pricing.md index 3b9b9c0d4..3aca5b44e 100644 --- a/playfab-docs/live-service-management/game-configuration/experiments/pricing.md +++ b/playfab-docs/live-service-management/game-configuration/experiments/pricing.md @@ -12,14 +12,14 @@ ms.localizationpriority: medium # Billing for PlayFab Experiments -This document describes how Experiments are metered and billed. In PlayFab's free Development mode, titles can use Experiments without a fee as long the aggregate number of player accounts is less than 100,000 (attempts to create additional player accounts will fail). For Live titles (on the pay-as-you-go model – Standard, Premium, or Enterprise), Experiments is billed under the [Insights credit system](../../../pricing/Meters/meters.md#insights) with no consumption limits. Insights credits are a virtual currency that allows all Insights services to be billed through a common value. Please note, Experiments service operation has no association with the performance characteristics control of Insights service. +This document describes how Experiments are metered and billed. In PlayFab's free Development Mode, titles can use Experiments without a fee as long the aggregate number of player accounts is less than 1000 (attempts to create additional player accounts will fail). For Live titles (on the pay-as-you-go model – Standard, Premium, or Enterprise), Experiments is billed under the [Insights credit system](../../../pricing/Meters/meters.md#insights) with no consumption limits. Insights credits are a virtual currency that allows all Insights services to be billed through a common value. The Experiments service operation has no association with the performance characteristics control of Insights service. The [billing summary page](../../../pricing/billingDetails.md) page provides a daily snapshot of your month-to-date estimate charges with Experiments service’s Insights credit as breakdown. Admin or billing permissions are required to view the Billing Summary page. The comprising factors, which account for the accrued Insights credits based on the consumption of the Experiments service are below. What factors contribute to the consumption billing for Experiments service under Insights meter? The metering starts only during the run of an experiment and stops when the experiment is completed or stopped. There are three key factors used to bill additional Insights credit utilization for Experiments service. 1. Size of the target audience for treatment assignment. The participating audience of an experiment is either all the active players or is determined based on the selected Segment’s computation in a real-time manner. Also, the process of assignment and instrumentation of a treatment configuration is done by stamping variant IDs onto the player profile. So, the larger the target audience, the more resources are consumed, which results in higher Insights metering. -2. Computation of metrics. This is measured in analysis computation job minutes for each scorecard. This is variable and the determining factors are the set of metrics (that is, each metric’s definition and complexity) and the number of relevant Entity events (with type ‘player’) associated with the involved metric set. So, the larger the associated event set (PlayStream or Telemetry) for a metric set, the higher the Insights metering. Please note, currently, we support a predefined metric set, so there are only two events—player_logged_in and player_realmoney_purchase—for which the scorecard computation happens, and the events’ variable size could add to the computation job minutes. +2. Computation of metrics. This is measured in analysis computation job minutes for each scorecard. This is variable and the determining factors are the set of metrics (that is, each metric’s definition and complexity) and the number of relevant Entity events (with type ‘player’) associated with the involved metric set. So, the larger the associated event set (PlayStream or Telemetry) for a metric set, the higher the Insights metering. A predefined metric set is supported, so there are only two events—player_logged_in and player_realmoney_purchase—for which the scorecard computation happens, and the events’ variable size could add to the computation job minutes. 3. Experiment duration. The longer the duration of an experiment, the higher the consumption of the Experiments service, which results in higher Insights metering. -Please note, the [Experiment APIs](/rest/api/playfab/experimentation/experimentation) and [PlayStream events](../../../api-references/events/index.md) are accounted for outside of the Insights credit system. The Experiment APIs along with the Overrides assignment usage are accrued under the [profile read/ writes meters](../../../pricing/Meters/meters.md#profile). Also, the Experiments’ PlayStream events are accrued under the [events meters](../../../pricing/Meters/meters.md#events). +Note: the [Experiment APIs](/rest/api/playfab/experimentation/experimentation) and [PlayStream events](../../../api-references/events/index.md) are accounted for outside of the Insights credit system. The Experiment APIs along with the Overrides assignment usage are accrued under the [profile read/ writes meters](../../../pricing/Meters/meters.md#profile). Also, the Experiments’ PlayStream events are accrued under the [events meters](../../../pricing/Meters/meters.md#events). diff --git a/playfab-docs/player-progression/statistics/quota-statistics.md b/playfab-docs/player-progression/statistics/quota-statistics.md index 7e34dabaf..fc75a393a 100644 --- a/playfab-docs/player-progression/statistics/quota-statistics.md +++ b/playfab-docs/player-progression/statistics/quota-statistics.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # Quota limits statistics The Statistic service is designed to align with PlayFab's pricing models, offering two distinct modes: -development and live. The development mode allows titles to test each feature and begin development. +development and live. The Development Mode allows titles to test each feature and begin development. The live mode, on the other hand, is optimized for handling larger traffic loads typical of a live game. The following tables outline the limits for each of these modes: diff --git a/playfab-docs/pricing/account-upgrades.md b/playfab-docs/pricing/account-upgrades.md index c52312f0a..7ac2d665a 100644 --- a/playfab-docs/pricing/account-upgrades.md +++ b/playfab-docs/pricing/account-upgrades.md @@ -1,5 +1,5 @@ --- -title: Account Upgrades +title: Account upgrades author: nathankong-microsoft description: Describes how to upgrade an account in the new Game Manager experience. ms.author: jenelleb @@ -10,16 +10,16 @@ keywords: playfab, pricing, upgrade, upgrades, launch, live ms.localizationpriority: medium --- -# Account Upgrades +# Account yupgrades Customers can upgrade their account plan using the self-serve plans experience found in Game Manager. -## Account Plans +## Account plans A PlayFab account has five plan options: -1. **FREE TO START :** This plan has no cost to the customer. Studios that belong to free accounts may only contain titles that are in [development-mode.md](development-mode.md). Once a title reaches its development mode limits, it must be launched by upgrading to a paid plan. To learn how to launch a title, see Title Launches.Once a title reaches its development mode limits, it must be launched by upgrading to a paid plan. To learn how to launch a title, see Title Launches. -2. **PAY-AS-YOU-GO :** This paid plan has no monthly base rate. Accounts are only charged for their monthly consumption for live titles. -3. **STANDARD :** This paid plan has a monthly base rate and private support options ([PaidTechnicalSupport.md](Support.md)). This plan comes with included meter usage amounts that live titles associated with the account may access. Once the included meter amounts have been used, the account will be charged for additional consumption. -4. **PREMIUM :** This paid plan has a monthly base rate and private support options ([PaidTechnicalSupport.md](Support.md)). This plan comes with more included meter usage than the Standard plan. Once the included meter amounts have been used, the account will be charged for additional consumption. -5. **ENTERPRISE :** An Enterprise account has a monthly base rate and private support channels that offer 24/7 assistance. This plan comes with more included meter usage than the Premium plan. Once the included meter amounts have been used, the account will be charged for additional consumption. An account can upgrade to an Enterprise plan through contacting the [https://playfab.com/contact/](https://playfab.com/contact/) . +1. **FREE TO START:** This plan has no cost to the customer. Once a title reaches its Development Mode limits, it must be launched by upgrading to a paid plan. To learn how to launch a title, see Title Launches. +2. **PAY-AS-YOU-GO:** This paid plan has no monthly base rate. Accounts are only charged for their monthly consumption for live titles. +3. **STANDARD:** This paid plan has a monthly base rate and private support options ([PaidTechnicalSupport.md](Support.md)). This plan comes with included meter usage amounts that live titles may access. Once the included meter amounts have been used, the account will be charged for additional consumption. +4. **PREMIUM:** This paid plan has a monthly base rate and private support options ([PaidTechnicalSupport.md](Support.md)). This plan comes with more included meter usage than the Standard plan. Once the included meter amounts have been used, the account will be charged for additional consumption. +5. **ENTERPRISE:** An Enterprise account has a monthly base rate and private support channels that offer 24/7 assistance. This plan comes with more included meter usage than the Premium plan. Once the included meter amounts have been used, the account will be charged for additional consumption. The base rate's included consumption is cumulative across titles linked to an account. @@ -27,18 +27,17 @@ The base rate's included consumption is cumulative across titles linked to an ac > All PlayFab account plans adhere to the [https://playfab.com/terms/](https://playfab.com/terms/). -## Understanding the Account-Studio-Title Relationship +## Understanding the account-studio-title relationship An account is linked to one Studio and a Studio may be linked to many titles. Upgrades are executed at the account level and launches are executed at the Title level. ![Image: Account-Studio-Title Relationship](pricingV2-media/AccountStudioTitleRelationship.png) -## Changing Plans +## Changing plans You can change your account's plan via Game Manager using the **Plan Recommendation** and **Plan Selection** pages. Plan changes are scheduled for the beginning of the next billing period. -### Upgrading from Free to Start +### Upgrading from free-to-start You can upgrade your account plan at any time on the **My Studios and Titles** page. Use the following steps to upgrade your account from Free to Start. Upgrading an account will upgrade all studios owned by the account. -1. Log in to [http://developer.playfab.com/](http://developer.playfab.com/). 1. Log in to [http://developer.playfab.com/](http://developer.playfab.com/). 2. On the **My Studios and Titles** page, locate the header of a Studio whose linked account should be upgraded. Select **Upgrade Account**. @@ -53,7 +52,7 @@ You can upgrade your account plan at any time on the **My Studios and Titles** p After an account is upgraded, the provided payment instrument is charged a monthly base rate per account in addition to usage charges for launched titles. -### Upgrading and Downgrading +### Upgrading and downgrading You can upgrade or downgrade your account plan at any time on the Studio Settings page of any studio owned by the account. Use the following steps to change your account's plan. Changing the account plan will change all studios owned by the account. 1. Log in to [http://developer.playfab.com/](http://developer.playfab.com/). @@ -68,11 +67,11 @@ You can upgrade or downgrade your account plan at any time on the Studio Setting 6. Once you upgrade your account, on the **Studio Settings** page under the Studio Plan section, you will see your current plan as well as the scheduled plan. -### Upgrading to Enterprise +### Upgrading to enterprise Any account is eligible to upgrade to an Enterprise account plan. The PlayFab team must be contacted to upgrade to an Enterprise account plan. [https://playfab.com/contact/](https://playfab.com/contact/) -### Cancel All Charges and Delete Your Studio +### Cancel all charges and delete Your sFtudio Before proceeding with deletion, consider the following recommended (but optional) actions to ensure a smooth transition and avoid any unintended loss: diff --git a/playfab-docs/pricing/billingDetails.md b/playfab-docs/pricing/billingDetails.md index 7b87dc633..3f3ae7cc0 100644 --- a/playfab-docs/pricing/billingDetails.md +++ b/playfab-docs/pricing/billingDetails.md @@ -14,12 +14,12 @@ ms.localizationpriority: medium Admin or billing permissions are required to view the **Billing Summary** page. -The billing details page provides a daily snapshot of your month-to-date estimate charges. Use the information on this page to estimate what your bill will look like at the end of the month and view past months to understand trends and comparisons. The billing details page helps you determine what the biggest consumers of your metered resources are and gives you information that you can use to reduce your charges in subsequent months. +The billing details page provides a daily snapshot of your month-to-date estimate charges. Use the information on this page to estimate what your bill looks like at the end of the month and view past months to understand trends and comparisons. The billing details page helps you determine what the biggest consumers of your metered resources are and gives you information that you can use to reduce your charges in subsequent months. > [!NOTE] > The values reported on the billing summary page are an **estimate** of usage and associated costs for an account. The amount shown might not depict the final invoice amount charged to an account. -To view the billing details page for your studio navigate to the My Studios and Titles page. Click the ellipsis on the right side of your studio, and then selecting the Billing summary option in the drop-down. +To view the billing details page for your studio, navigate to the My Studios and Titles page. Click the ellipsis on the right side of your studio, and then selecting the Billing summary option in the drop-down. ## Billing Summary Overview @@ -30,9 +30,9 @@ To view the billing details page for your studio navigate to the My Studios and 2. **Selected Month** * This is the month that the listed consumption and charges cover. Use the Month Filter (8) to change the selected month. 3. **Month-To-Date (MTD) Estimated Charge** - * This is the daily snapshot of estimated total charges that your studio has accrued during the selected calendar month. + * This is the daily snapshot of estimated total charges that your studio accrues during the selected calendar month. 4. **The Fine Print** - * Only use the **Billing Summary** page as an estimate for your month-to-date charges. Some meters have a 48+ hour delay and the **Billing Summary** page does not include all chargeable items (For example, Add-ons). On the first of the current month, you can view the final estimate for the previous month's charges (excluding taxes and delayed meter charges), and on the second of the current month, you can view the first estimate for the current month's usage and costs. + * Only use the **Billing Summary** page as an estimate for your month-to-date charges. Some meters have a 48+ hour delay and the **Billing Summary** page doesn't include all chargeable items (For example, Add-ons). On the first of the current month, you can view the final estimate for the previous month's charges (excluding taxes and delayed meter charges), and on the second of the current month, you can view the first estimate for the current month's usage and costs. 5. **.csv Download** * You can download the **Billing Summary** view to .csv for further analysis. The "Download Summary" provides the same granularity as the **Billing Summary** page. The "Download daily" provides the daily breakdown of usage. > [!NOTE] @@ -40,19 +40,19 @@ To view the billing details page for your studio navigate to the My Studios and 6. **Contact Information** * This is the contact information we use to send you an invoice. This can be changed by navigating to the **Billing Information** page. 7. **Title Filter** - * Use the **Title** filter to understand consumption and apportioned cost by title. Namespace events are counted in the "All" calculation, but aren't currently available to drill down (as they aren't tied to a title). Development mode titles are not charged to the account and do not display cost data. + * Use the **Title** filter to understand consumption and apportioned cost by title. Namespace events are counted in the "All" calculation, but aren't currently available to drill down (as they aren't tied to a title). Development Mode titles aren't charged to the account and don't display cost data. 8. **Month Filter** * Use this filter to choose the month to display. All billing summary data from the time the account was updated to usage-based pricing is visible through the billing summary page. 9. **Meter Category** * The **Pay as you Go** section buckets the full set of meters into logical categories. You can find the full set of meters in [meter documentation](Meters/meters.md). 10. **Meter** - * This is a billable meter that at least one of your titles is consuming. You only see meters that you are using. For a full list of meters, see [meter documentation](Meters/meters.md). + * This is a billable meter that at least one of your titles is consuming. You only see meters that you're using. For a full list of meters, see [meter documentation](Meters/meters.md). 11. **Usage** - * This column provides estimated, rounded usage (for readability purposes) for each tier/SKU, as well as the aggregated amount. To see the exact usage, download the .csv (5). + * This column provides estimated, rounded usage (for readability purposes) for each tier/SKU, and the aggregated amount. To see the exact usage, download the .csv (5). 12. **Rate** - * This column provides the rounded rates (for readability purposes) for each tier/SKU. To see the exact rates, please download the .csv (5). + * This column provides the rounded rates (for readability purposes) for each tier/SKU. To see the exact rates, download the .csv (5). 13. **Cost** - * This column provides the estimated cost for each tier/SKU, as well as the aggregated amount. + * This column provides the estimated cost for each tier/SKU, and the aggregated amount. 14. **Description** * Each meter provides a brief description in the billing summary page. You can find a more detailed explanation of the meters in [meter documentation](Meters/meters.md). @@ -62,18 +62,18 @@ To view the billing details page for your studio navigate to the My Studios and The base rate charge includes: -1. **Meter usage** amounts that are specified at [PlayFab pricing](https://www.playfab.com/pricing). Once meter usage across live titles associated to an account has surpassed the included amounts (above), an account's live title usage will be charged based on the meter rates found at [PlayFab pricing](https://www.playfab.com/pricing) (also listed under the "Rate" column on the Billing Summary page). These costs are referred to as "Pay-As-You-Go" charges. +1. **Meter usage** amounts that are specified at [PlayFab pricing](https://www.playfab.com/pricing). Once meter usage across live titles associated to an account surpasses the included amounts (above), an account's live title usage is charged based on the meter rates found at [PlayFab pricing](https://www.playfab.com/pricing) (also listed under the "Rate" column on the Billing Summary page). These costs are referred to as "Pay-As-You-Go" charges. > [!NOTE] - > Titles in [Development Mode](development-mode.md) are not counted against included base rate usage. + > Titles in [Development Mode](development-mode.md) aren't counted against included base rate usage. 2. **[Technical support](Support.md)** that is determined by the [account level](account-upgrades.md). ## Additional Section Definitions -**Pay-As-You-Go Charges:** Pay-As-You-Go charges are the cost of individual meter usage per title in an account that exceed usage amounts that are part of the plan. The per-meter prices can be found at [PlayFab pricing](https://www.playfab.com/pricing) or under the "Rate" column on the billing summary page. +**Pay-As-You-Go Charges:** Pay-As-You-Go charges are the cost of individual meter usage per title in an account that exceeds usage amounts that are part of the plan. The per-meter prices can be found at [PlayFab pricing](https://www.playfab.com/pricing) or under the "Rate" column on the billing summary page. -**Additional Charges:** Additional charges include any charges not directly tied to the meter-usage pricing plan. For example, charges for MPS and Add-Ons may appear in the additional charges section. +**Additional Charges:** Additional charges include any charges not directly tied to the meter-usage pricing plan. For example, charges for Multiplayer Servers (MPS) and Add-ons may appear in the additional charges section. ## Learn More diff --git a/playfab-docs/pricing/consumption-best-practices.md b/playfab-docs/pricing/consumption-best-practices.md index 5719a451a..0bb20ecb1 100644 --- a/playfab-docs/pricing/consumption-best-practices.md +++ b/playfab-docs/pricing/consumption-best-practices.md @@ -1,5 +1,5 @@ --- -title: PlayFab Consumption Best Practices +title: PlayFab consumption best practices author: joannaleecy description: Describes best practices for managing your costs in PlayFab. ms.author: jenelleb @@ -10,11 +10,11 @@ keywords: playfab, pricing ms.localizationpriority: medium --- -# PlayFab Consumption: Best Practices +# PlayFab consumption: best practices With PlayFab's consumption-based pricing model, you only pay for the actual service usage of your titles. But this raises an obvious question: how do you best optimize those titles to save money, while still implementing all the features you need? In this document, we dive into those details, and talk about best practices that will help you to plan ahead. -Before you move your titles from Development Mode to Live, you can review the meter information in the Billing Summary tab of the Game Manager. A good starting practice is to periodically confirm the meters by using a separate title to check meter usage for real-world-player activity. You can have multiple titles in Development Mode, so that you can create titles on the fly as you reach development stages where you want to checkpoint that usage, and then delete those titles after you're done. +Before you move your titles from Development Mode to Live, you can review the meter information in the Billing Summary tab of the Game Manager. There are six consumption meters: Events, Profile, Content and Configuration, CloudScript, Insights, and Multiplayer Services. The best way to begin optimizing a title is to look at each of the meters that it uses and see how it accumulates over time. This allows you to quickly derive some obvious improvements. For more information about meters, see [Pricing Meters](Meters/meters.md). @@ -42,7 +42,7 @@ For more information about the specific API calls that result in "spin" on these We'll start with User Data and Statistics, since their usage patterns are similar, and then we'll talk about player inventory management. -### Data and Statistics +### Data and statistics When evaluating your usage of User Data, the same approximation logic as for events applies–each 1 KB increases the meter count by 1–though keep in mind that each "element" of a call should be thought of as distinct for purposes of this calculation. Each key value pair in a call to update User Data is counted separately. For reads, this 1 KB calculation applies to the total data returned, regardless of the number of key value pairs. This means that writing 10 keys of 100 bytes each is 10 "ticks" of the profile write meter, since each key value pair write is a minimum of 1 KB, while a read of those 10 keys is 1 "tick", since it's a total of 1 KB. For more specific details on the usages, see [Pricing meters](Meters/meters.md). @@ -54,7 +54,7 @@ If you're coming from PC or console development–especially single player games How do you determine the optimal frequency of reads and writes? Two of the most common concerns of developers who want to update data and statistics more frequently are protecting against cheating, and having timely information stored server-side either for player-to-player interactions or to prevent data loss if the game exits unexpectedly. -### Cheat Protection +### Cheat protection While it might seem like you need to constantly update your backend data to ensure essential security, frequent updates are rarely necessary if your game doesn't require fully server-authoritative control of the session. To start, the fundamental question is how much security that you actually need. @@ -72,7 +72,7 @@ For games with more real-time requirements, such as needing to update the server This is the model used by real-time multiplayer games. It's also a valid technique for single-player titles that require server-authoritative checks, though if that frequency is only a few times a minute per player, Azure Functions CloudScript could be the better option. The total CloudScript cost is easy to compute. It's the total gigabyte-seconds that you consume, with a minimum of 128 MB and 100 ms per execution, plus the normal calculations for any other service API calls the script uses. For example, if you have a total memory footprint, between your script code and variable usage in the script, of 250 MB, you would need to run that script for 4 seconds (across multiple users, most likely) to get to 1 GB/s. And within that script code, if you read or write Entity Objects, Title Data, User Data, etc., you'll need to calculate the spin that each of those calls has on the profile meters. Since hosted game server costs are dependent on how many servers you're running, and that in turns depends upon how many players can be hosted on a server at a time, it's not necessarily trivial to determine where the break-even point is between the two. But if you find that you need to call your scripts at a high frequency, and need to read and write data from the service each time, it's very likely that a game server solution is the better way to go. -### Data Timeliness +### Data timeliness One common theme we've heard among developers with high profile write rates is that they're concerned about the player losing progress. If the player exits the game before it can save and the local state can't be used the next time the game is played, or that state needs to travel between devices, you want to have the PlayFab-stored state information for the player be as up-to-date as possible. @@ -93,7 +93,7 @@ For competition, [Leaderboards](../community/leaderboards/index.md) are an ideal For games that use cross-player data directly in the session, the most common optimization is to read only the information about the few specific players with whom the local player is interacting. For real-time action games, this is usually done on the server hosting the session. For others–such as games where players can attack each others' bases–the most common approaches are to either read all that data onto the local device or to send the local player only the subset of the other player's data that the local player should know. Games that do the former use server-side logic to evaluate the final results the client sends. Games that do the latter update the data iteratively over the course of the session with more data, when the local player should have access to it. But even then, they also use server-side logic to evaluate the final results. Again, the tipping point in deciding whether this should be done through script or on a hosted server is down to frequency. If it's more than a few times a minute, you're better off using a hosted server for the portion of the session that requires that data. -## Economy and Inventory +## Economy and inventory Inventory, and economy in general, requires a different approach. There's no avoiding the fact that if a player is giving up something of real (money) or perceived (virtual currency or consumable containers) value, they have an implicit expectation that the transaction will be honored. For any game with in-app purchases, an increment to the profile meter for a purchase made by the player with real-world currency is a trivial cost. In many types of games, inventory updates are infrequent enough to pose little concern for greatly increasing your overall usage. But for those with more frequent inventory updates–even if you don't have in-game monetization–there are optimization tricks to help reduce your costs. @@ -103,7 +103,7 @@ When it comes to games that have higher rates of update to inventory, we're back By their nature, certain game genres, such as collectible card games, do need to update the player inventory at a somewhat higher rate. But even here, there are still opportunities to aggregate inventory changes and reduce the total usage on the profile meters. For example, in games that use [drop tables](../economy-monetization/economy/tutorials/drop-tables.md), the design frequently employs a container that has one or more "pulls" from each of several different drop tables. Typically, if these pulls are only an occasional action the incremental cost is small enough to not cause concern. But if players can collect many of those containers, and open multiples in a short period of time, you could provide an "open N" or even "open all" option. In that case, you use [PlayFab CloudScript using Azure Functions](../live-service-management/service-gateway/automation/cloudscript-af/index.md) or your custom game server to either query [Player Item Management - Get Random Result Tables](xref:titleid.playfabapi.com.server.playeritemmanagement.getrandomresulttables) for the set of drop tables or call [Player Item Management - Evaluate Random Result Table](xref:titleid.playfabapi.com.server.playeritemmanagement.evaluaterandomresulttable) without generating the inventory items. You could then update the player inventory far more efficiently by only adding instances where needed, and then updating the count of item stacks for the rest. -## Content and Configuration +## Content and configuration Where the Profile is primarily about the player, Content and Configuration is primarily about the title. A number of title-level components, such as Push Notifications, email services, and Title News are all included in this meter. In addition though, this is the meter used to track on Entity File usage. Similarly, requests for the URLs for uploading and downloading CDN files are tracked on this meter, though it's important to clarify that CDN costs are separate, and are billed based on the total gigabytes downloaded as described in [Content Delivery Network (CDN)](../data-analytics/legacy/content-delivery-network/index.md). The calculation of the Content and Configuration read and storage meters are similar to the Profile meters in that they're based on the size of the data, though obviously the units are significantly larger than 1 KB. For the Content and Configuration write meter, it's solely based on the total number of write operations, with each incrementing the meter by 1. @@ -129,7 +129,7 @@ For information about Insights and how to use it, see [What is PlayFab Insights] For information about Insight best practices, see [Best Practices & FAQ](../data-analytics/legacy/insights/best-practices.md). -## Multiplayer Services +## Multiplayer services This one is the simplest of all, since the pricing is completely unchanged. In short, hosted [Multiplayer Servers](../multiplayer/servers/index.md) and the [Party service](../multiplayer/networking/index.md) have always been charged on a usage basis. @@ -137,9 +137,7 @@ For hosted game servers specifically, you can minimize your costs by optimizing If low ping times are important on those servers, you can choose which regions to run the servers. For most games, the largest concentrations of players are limited to certain key regions, but if you have a widely dispersed player population—particularly when you're in the long tail of your game—you'll need to weigh the cost of running servers in every region near your players versus the impact of longer ping times on the subset of players in areas with few players. One thing that can help with that is to make sure you're using our [QOS service](../multiplayer/servers/using-qos-beacons-to-measure-player-latency-to-azure.md) to choose which regions to put players in, and then determine what your cut-off is for the minimum number of players you need playing in a region for it to be viable. -To help get you through development without running up costs, we provide a significant number of free server hours in our hosting service, and our Party service is free for all Development Mode titles. It's also worth calling out that our Party service is also free for all use with Xbox Live signed-in players, and for titles in our Standard, Premium, and Enterprise tiers, we provide a generous allowance of connectivity, voice, and Cognitive Services (voice transcription and translation) at no additional cost, to help with 21st Century Communications and Video Accessibility Act (CVAA) compliance. - -## Managing your Live Game +## Managing your live game That covers the fundamentals of the meters, but what should you be thinking about once your title is live? Managing your community of players primarily involves analytics ([Insights](#insights), in the section above) and updates to Content and Configuration. In addition, most games need to engage with players outside their normal interactions with the game itself. From re-engagement campaigns (to entice players to come back), to community rewards for meta-game activity, and even to thanking players for their own community work outside the game, a common practice these days is to use [LiveOps](https://playfab.com/liveops/) techniques to keep players highly engaged. diff --git a/playfab-docs/pricing/development-mode.md b/playfab-docs/pricing/development-mode.md index 6aaaee5c5..8f27395ce 100644 --- a/playfab-docs/pricing/development-mode.md +++ b/playfab-docs/pricing/development-mode.md @@ -1,7 +1,7 @@ --- -title: Development mode +title: Development Mode author: joannaleecy -description: Describes the features and limits of Development mode titles. +description: Describes the features and limits of Development Mode titles. ms.author: jenelleb ms.date: 09/09/2020 ms.topic: article @@ -10,38 +10,41 @@ keywords: playfab, pricing, dev mode, development mode, title, meter, meters ms.localizationpriority: medium --- -# Titles in Development mode +# Titles in Development Mode > [!IMPORTANT] -> When you're ready to scale up, it's important to make sure you switch your title from "Development mode" to "Live." To make this change, use the **Launch** button on the Game Overview page or the PlayFab main dashboard. This change ensures that the title isn't limited to 100,000 unique users. +> When you're ready to scale up, it's important to make sure you switch your title from "Development Mode" to "Live." To make this change, use the **Launch** button on the Game Overview page or the PlayFab main dashboard. This change ensures that the title isn't limited to 100 unique users. -All PlayFab titles are in one of two possible states - development mode and live. Development mode is, as the name suggests, meant for titles currently in development. This mode provides developers with the flexibility to connect a title to PlayFab without running up the bill. +> [!NOTE] +> Development Mode is being replaced by Foundation Mode as of March 11, 2026. To access PlayFab services with no monthly bill for the duration of your development cycle, we recommend [creating new titles in Foundation Mode](../get-started/foundation-onboarding.md). All titles that ship to an Xbox storefront will also get Foundation Mode services included as part of their platform agreement. -A game in development mode can have up to 100,000 unique users. These titles can be [launched](title-launches.md) through Game Manager and is then considered live. Launching a title removes all development mode limitations and allows the title to expand outside of test markets. +Developers can evaluate PlayFab services risk free using Development Mode, with no monthly bills up to the first 1000 unique users. Once a title in Development Mode hits this limit, no additional users can be created until a title is moved to a live mode. -By default, every title created starts in development mode. The **My Studios and Titles** main page indicate which state a title is in through a mark on the bottom, left corner of the title block. This indicator can also be viewed at the top of the left nav within a title. Titles in development mode are labeled **Development**. Live titles are blank. +Titles can be [launched](title-launches.md) through Game Manager and is then considered live. Launching a title removes all Development Mode limitations. -**My Studios view of development mode title tag** +By default, every title created starts in Development Mode. The **My Studios and Titles** main page indicate which state a title is in through a mark on the bottom, left corner of the title block. This indicator can also be viewed at the top of the left nav within a title. Titles in Development Mode are labeled **Development**. Live titles are blank. -![My Studios view of development mode title tag](pricingV2-media/development-mode-title-tag.png "My Studios view of development mode title tag") +**My Studios view of Development Mode title tag** -**Title page view of development mode title tag** +![My Studios view of Development Mode title tag](pricingV2-media/development-mode-title-tag.png "My Studios view of Development Mode title tag") -![Title page view of development mode title tag](pricingV2-media/dev-mode-title-tag-titlePage.PNG "Title page view of development mode title tag") +**Title page view of Development Mode title tag** + +![Title page view of Development Mode title tag](pricingV2-media/dev-mode-title-tag-titlePage.PNG "Title page view of Development Mode title tag") **Live title with blank tag** ![Live title with blank tag](pricingV2-media/live-mode-title.PNG "Live title with blank tag") > [!NOTE] -> As long as your title is in development mode, consumption isn't counted towards any of your billable meters. +> As long as your title is in Development Mode, consumption isn't counted towards any of your billable meters. The example below shows how meter consumption is reflected in the billing for a fictional customer called Fun Studios: | Title | Title mode | Meter Consumption | | --- | --- | --- | | Fun Game | Live | 1 million PlayStream events | -| Fun Game 2: The Return of Fun | Development mode | 100,000 PlayStream events +| Fun Game 2: The Return of Fun | Development Mode | 100,000 PlayStream events When Fun Studios visits their Billing Summary page, they only see the consumption for their Live title, Fun Game, count against their Standard Plan included resources. @@ -53,19 +56,19 @@ When Fun Studios visits their Billing Summary page, they only see the consumptio ## Limits -There are some studio and title limits associated with development mode: +There are some studio and title limits associated with Development Mode: ### Studio limits | Limit | Amount | | --- | --- | -| Titles in Development mode | 10 Titles | +| Titles in Development Mode | 10 Titles | ### Title limits | Limit | Amount | | --- | --- | -| Unique users | 100,000 users created | +| Unique users | 1000 users created | | PlayStream events | 1 million events | | Telemetry events | 1 million events | | Profile reads | 5 million reads | @@ -85,7 +88,7 @@ There are some studio and title limits associated with development mode: | Insights credits | Insights Performance Level 1 | **Definition of unique users:** -Unique users are the total number of players ever created in your development mode title, which is distinct from monthly active users or daily active users. +Unique users are the total number of players ever created in your Development Mode title, which is distinct from monthly active users or daily active users. > [!NOTE] > You can learn more about title limits at [PlayFab Pricing](https://www.playfab.com/pricing). diff --git a/playfab-docs/pricing/pricing-overview.md b/playfab-docs/pricing/pricing-overview.md index 052b22994..01196940a 100644 --- a/playfab-docs/pricing/pricing-overview.md +++ b/playfab-docs/pricing/pricing-overview.md @@ -15,7 +15,7 @@ ms.localizationpriority: medium 1. **[Billing Summary](billingDetails.md):** View past and present estimated costs. -2. **[Development Mode](development-mode.md):** Understand technical limits applied to titles in development mode. +2. **[Development Mode](development-mode.md):** Understand technical limits applied to titles in Development Mode. 3. **[Pricing Meters](Meters/meters.md):** Learn about meter pricing and related APIs. diff --git a/playfab-docs/pricing/title-launches.md b/playfab-docs/pricing/title-launches.md index cc7a6ebf9..43ad44195 100644 --- a/playfab-docs/pricing/title-launches.md +++ b/playfab-docs/pricing/title-launches.md @@ -18,26 +18,23 @@ Customers can upgrade their account plan and launch titles using the self-servic A PlayFab title has two possible modes. -1. **Development mode:** A title in development mode doesn't incur costs when you're using the core services. Use this mode to experiment with most of PlayFab offerings. A title in development mode is subjected to specific total player accounts and meter usage limits as determined by PlayFab. For more information about the included limits, see [development-mode.md](development-mode.md). - - > [!NOTE] - > [Multiplayer server hosting](../multiplayer/servers/billing-for-thunderhead.md), [Party](./Meters/meters.md#party), and [Insights](../data-analytics/legacy/insights/pricing.md) aren't part of the core services. But they do have limited free usage available in Development mode. +1. **Development mMde:** A title in Development Mode doesn't incur costs when you're using the core services. Use this mode to experiment with most of PlayFab offerings. A title in Development Mode is subjected to specific total player accounts and meter usage limits as determined by PlayFab. For more information about the included limits, see [development-mode.md](development-mode.md). 1. **Live:** A live title uses metering to measure your usage. You're charged according to the paid service account plan and rate. Any meter usage over what is included in the account plan's base rate results in charges per meter consumed. For more information, see [Meters/meters.md](Meters/meters.md). > [!NOTE] - > Your title could still be in development when your PlayFab title is Live. In the same way, you could have actual players in the game when the PlayFab title is in Development mode. A title in Development mode will continue to have the total player accounts limit as determined by PlayFab. Moving to Live removes that limit. To convert a title from Development mode to Live, go to the title in PlayFab portal and select the **Launch** button. For instructions, see below. + > Ensure you move your PlayFab title out of Development Mode before releasing your game. A title in Development Mode will continue to have the total player accounts limit as determined by PlayFab. Moving to Live removes that limit. To convert a title from Development Mode to Live, go to the title in PlayFab portal and select the **Launch** button. For instructions, see below. ## Launching a title > [!WARNING] -> Launching a title is a permanent action. The title cannot return to Development mode after the launch is completed. +> Launching a title is a permanent action. The title cannot return to Development Mode after the launch is completed. -To be able to move a title from Development mode to Live, a title must be in a Studio with a paid account plan. +To be able to move a title from Development Mode to Live, a title must be in a Studio with a paid account plan. ### Launching a title with a Free to Start plan -Titles may only be changed to Live in Studios owned by paid accounts. Follow the steps in the section below to upgrade your free account to a paid account first. After the upgrade, you'll see the launch option to switch your title from Development mode to Live. +Titles may only be changed to Live in Studios owned by paid accounts. Follow the steps in the section below to upgrade your free account to a paid account first. After the upgrade, you'll see the launch option to switch your title from Development Mode to Live. ### Launching a title within a Paid Account Plan @@ -45,7 +42,7 @@ To launch a title within a paid account plan: 1. Sign in to [https://developer.playfab.com/](https://developer.playfab.com/) -2. Navigate to the **My Studios** page and identify the **Development mode** title to be launched. +2. Navigate to the **My Studios** page and identify the **Development Mode** title to be launched. 3. Select the down arrow on the title to open the drop-down menu. @@ -57,18 +54,10 @@ To launch a title within a paid account plan: ## Frequently asked questions -Q: What happens when I launch my title for the world to sign up and play but it's still in PlayFab Development mode? +Q: What happens when I launch my title for the world to sign up and play but it's still in PlayFab Development Mode? -A: Because your title is in Development mode, it still has a 100K total player accounts limit. The core meters (Profile, Content and Configuration, and Events) continue to have no cost. When your title starts making a high number of service calls, it may be throttled, and would affect your overall player experience. To remove the player accounts limit, you have to move the title out of Development mode. At the same time, the core service meters start to charge your account normally, based on your tier of service. +A: Because your title is in Development Mode, there is a limit on the total number of player accounts that can be created in that title. Once your title reaches that limit, all requests to create new player accounts will be denied which will impact the player experience. To remove the player accounts limit, you have to move the title out of Development Mode. Q: I'm using the **Free to Start** plan. Do I need to switch my title to Live at launch? -A: In the **Free to Start** plan, you don't have the **Launch** option to switch your title from Development mode to Live. You must first upgrade to a paid tier (pay-as-you-go or higher) to have the launch option made available to you. - -Q: I'm only using PlayFab Party and it's free for Xbox Live users. What plan should I be using? - -A: You can choose to use any of the plans we offer—Pay-as-you-go, Standard, or Premium. You won't be charged when Xbox Live users use Party for chat and networking. - -Q: Do I have to switch my title to Live if I'm not expecting it to hit the **Free to Start** plan limits? - -A: You don't have to. However, it's worth noting that we don't support load testing of any kind in Development mode. That includes a limited release of a title to a closed community. If a title in Development mode starts making a high number of calls to the service, it may be throttled. +A: In the **Free to Start** plan, you don't have the **Launch** option to switch your title from Development Mode to Live. You must first upgrade to a paid tier (pay-as-you-go or higher) to have the launch option made available to you. \ No newline at end of file From 3647d6e1aefce9cd626ba1a28a551fc4146f9fc6 Mon Sep 17 00:00:00 2001 From: v-alje <4665434+v-alje@users.noreply.github.com> Date: Fri, 13 Mar 2026 19:12:03 +0000 Subject: [PATCH 71/76] Initialize Docs repository: https://github.com/MicrosoftDocs/playfab-docs-pr of branch live --- .openpublishing.publish.config.json | 14 +++++----- SECURITY.md | 41 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 SECURITY.md diff --git a/.openpublishing.publish.config.json b/.openpublishing.publish.config.json index bbf91ea6f..fb744d2ef 100644 --- a/.openpublishing.publish.config.json +++ b/.openpublishing.publish.config.json @@ -38,9 +38,7 @@ "branches_to_filter": [], "git_repository_url_open_to_public_contributors": "https://github.com/MicrosoftDocs/playfab-docs", "git_repository_branch_open_to_public_contributors": "docs", - "skip_source_output_uploading": false, "need_preview_pull_request": true, - "contribution_branch_mappings": {}, "dependent_repositories": [ { "path_to_root": "_themes", @@ -69,12 +67,15 @@ "Pdf" ] }, - "need_generate_pdf_url_template": true, "targets": { "pdf": { "template_folder": "_themes.pdf" } }, + "docs_build_engine": {}, + "skip_source_output_uploading": false, + "contribution_branch_mappings": {}, + "need_generate_pdf_url_template": true, "dependent_packages": [ { "id": "Microsoft.OpenPublishing.CommonPlugins", @@ -83,8 +84,5 @@ "target_framework": "net45", "version": "latest" } - ], - "docs_build_engine": { - "name": "docfx_v3" - } -} + ] +} \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..e138ec5d6 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + From fc41a078910fefaa18467d199803ac093b49bb65 Mon Sep 17 00:00:00 2001 From: "learn-build-service-prod[bot]" <113403604+learn-build-service-prod[bot]@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:29:14 -0700 Subject: [PATCH 72/76] =?UTF-8?q?Auto=20Publish=20=E2=80=93=20main=20to=20?= =?UTF-8?q?live=20-=202026-03-17=2017:00=20UTC=20(#2855)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initialize Docs repository: https://github.com/MicrosoftDocs/playfab-docs-pr of branch main * [PubSub] Rename "Notifications" to "Messages" in PubSub docs. Also add a note for PubSub clients about ensuring they set KeepAliveInterval (#2843) * [PubSub] Rename "Notifications" to "Messages" in PubSub docs. Also add a note for PubSub clients about ensuring they set KeepAliveInterval * Fix Acrolinx grammar issues to meet minimum 80 score - Fix possessive 'it's' -> 'its' in mpintro.md - Replace 'aka' with 'also known as' in mpintro.md - Replace 'e.g.' with 'for example' in mpintro.md - Fix 'ex:' -> 'for example' and missing 'be' in signalr-hub.md - Expand 'you're' -> 'you are' in signalr-hub.md - Fix double space and contractions in start-or-recover-session-response.md - Replace 'don't' with 'do not' across all 18 PubSub NOTE blocks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * retrigger checks * retrigger Acrolinx checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * acrolinx updates * acrolinx clarity --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update (#2841) Co-authored-by: OpenPublishing.Build * PlayStream Event Documentation Updates: Experimentation, PlayStream (actions), Segmentation, TargetedConfiguration (player churn) (#2826) * Add Experimentation events * Add Segmentation events * Add PlayStream actions events * Add player churn event * Fix typo in index.md * Fix some typos in index.md * move player-action-executed back to Player folder * Update table of contents with new event docs in this PR. * Game Saves linking doc (#2761) * Initial draft of linking doc * MS learn requirements * Fixing invalid apostrophe characters * Fixing a few header levels * Added suggested changes to sample code * Misc fixes * Fix correctness issues and Acrolinx style in linking.md - Replace XAsyncGetStatus with PFAuthenticationLoginWithXUserGetResultSize in Strategy 2 sample (XAsyncGetStatus doesn't return PF error codes) - Add note about RETURN_IF_FAILED in void XAsyncBlock callbacks - Fix typo: defered -> deferred - Acrolinx: login -> sign-in for user actions, add contractions, remove filler words, fix future tense, expand MSA acronym - Convert blockquote to [!TIP] callout for player-facing wording note - Add [!IMPORTANT] callout warning about static XAsyncBlock lifetime - Add caller-responsibility comments for heap-allocated context structs - Add See also section with links to related docs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refactor Strategy 2 sample code and add flow diagram - Extract helper functions: RunReconciliation, BeginLateLink, BootstrapViaXbox, CheckLinkStatusAndPrompt - Reduce max nesting from 7 levels to 4; RunStrategy2Flow drops from ~140 lines to ~55 lines - Add forward declarations and banner comments for each helper - Add Mermaid flowchart showing the complete Strategy 2 decision tree between the prose walkthrough and the sample code Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Mermaid diagram syntax for Learn and VSCode rendering Remove HTML br tags, Unicode special characters, and parentheses from Mermaid node/edge labels that prevented rendering. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Replace Mermaid code block with rendered SVG diagram Learn doesn't support Mermaid natively, so render the Strategy 2 flow diagram as an SVG image. The .mmd source is kept alongside the SVG in media/ for future regeneration via mmdc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove Strategy 2 sample code and polish flow diagram - Remove the ~330-line Strategy 2 C++ sample. The prose walkthrough and flow diagram provide sufficient guidance; a full working sample should be added separately. - Restyle the SVG diagram with a custom Learn-friendly theme (soft blue nodes, Segoe UI font) and add horizontal padding to edge labels. - Add mermaid-learn.json config for future diagram regeneration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix diagram description: single terminal node, not multiple Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Minor Acrolinx fixes in Strategy 1 prose - Add missing comma after introductory clause - 'will require' -> 'requires', 'can just go' -> 'can go' (present tense) - 'different than' -> 'different from' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add verification callout for cross-platform link on returning players When a title requires the cross-platform identity to match the currently signed-in user, a successful platform login alone isn't sufficient. Added a NOTE callout after the happy path advising titles to verify the link via GetAccountInfo. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix forceLink guidance to distinguish AccountAlreadyLinked vs LinkedAccountAlreadyClaimed forceLink only resolves LinkedAccountAlreadyClaimed (platform account claimed by another entity). It does not resolve AccountAlreadyLinked (entity already has a different platform account linked). The latter requires an explicit Unlink call before re-linking. Updated prose, sample code comments, and mermaid diagram to reflect the correct two-error handling. Also fixed SVG background to transparent for dark mode support. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review feedback: style and terminology fixes - Convert all headings from title case to sentence case (DocuMentor rule) - Replace 'e.g.' with 'for example,' (8 instances) - Hyphenate 'first-party' and 'free-to-play' as compound adjectives - Fix 'OpenId Connect' to 'OpenID Connect' - Add backticks around LoginWithXbox and LoginWithOpenIdConnect - Use contraction 'wasn''t' instead of 'was not' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix sample code and error names verified against PlayFab.C source Verified linking.md claims against PlayFab.C SDK headers using the AGENTS.md bootstrap context added to PlayFab.C. Four issues found and fixed: 1. PFAccountManagementClientLinkSteamAccountGetResult does not exist - LinkSteamAccount is a void async op. Replaced with XAsyncGetStatus. 2. forceLink field is bool const* (optional pointer), not bool. The previous code set the pointer to null via 'false', which accidentally worked but would crash if set to 'true'. Replaced with commented-out pointer pattern showing correct usage. 3. Added ticketIsServiceSpecific field (required when using GetAuthTicketForWebApi with AzurePlayFab identity string). 4. Replaced service-side error string names (LinkedAccountAlreadyClaimed, AccountAlreadyLinked) with SDK HRESULT constants (E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED, E_PF_ACCOUNT_ALREADY_LINKED) throughout prose, tables, and code comments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jason Sandlin * Update Playfab release notes for 260313 (#2854) * Update Playfab release notes for 260313 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --------- Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --------- Co-authored-by: v-alje <4665434+v-alje@users.noreply.github.com> Co-authored-by: Warren Alpert <1860902+WarrenAlpert@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: learn-build-service-prod[bot] <113403604+learn-build-service-prod[bot]@users.noreply.github.com> Co-authored-by: OpenPublishing.Build Co-authored-by: Joel Kucera Co-authored-by: Andy McCalib Co-authored-by: Jason Sandlin Co-authored-by: Steven Rojas Lizano Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --- .openpublishing.redirection.json | 162 +++++-- .../exclusion-group-created.md | 27 ++ .../exclusion-group-deleted.md | 25 ++ .../exclusion-group-updated.md | 27 ++ .../Experimentation/experiment-created.md | 29 ++ .../Experimentation/experiment-deleted.md | 26 ++ .../experiment-start-requested.md | 30 ++ .../experiment-stop-requested.md | 27 ++ .../Experimentation/experiment-updated.md | 29 ++ .../player-experiment-variants-changed.md | 26 ++ .../events/PlayStream/action-executed.md | 27 ++ .../events/PlayStream/action-failed.md | 27 ++ .../events/Player/player-action-executed.md | 4 +- .../events/Segmentation/api-operation.md | 33 ++ .../events/Segmentation/segment-entered.md | 26 ++ .../events/Segmentation/segment-exited.md | 26 ++ .../player-churn-prediction-changed.md | 25 ++ .../events/data-types/actioneventdetails.md | 23 + .../events/data-types/actionfailure.md | 22 + .../events/data-types/actionresultdetails.md | 22 + .../events/data-types/actiontrigger.md | 27 ++ .../events/data-types/actiontype.md | 31 ++ .../events/data-types/churnrisklevel.md | 24 ++ .../events/data-types/experiment.md | 26 ++ .../data-types/experimentrequestorigin.md | 22 + .../events/data-types/experimentvariable.md | 22 + .../events/data-types/experimentvariant.md | 26 ++ .../events/data-types/segmentoperation.md | 24 ++ .../data-types/segmentoperationstatus.md | 24 ++ playfab-docs/api-references/events/index.md | 56 ++- playfab-docs/api-references/toc.yml | 42 +- .../google-html5.md | 2 +- ...lobby-and-matchmaking-client-sdk-errors.md | 4 +- ...bby-and-matchmaking-real-time-messages.md} | 48 +-- .../lobby-and-matchmaking-release-notes.md | 2 +- playfab-docs/multiplayer/lobby/toc.yml | 4 +- .../matchmaking/backfill-tickets.md | 2 +- .../multiplayer/matchmaking/quickstart.md | 4 +- playfab-docs/multiplayer/matchmaking/toc.yml | 4 +- playfab-docs/multiplayer/mpintro.md | 8 +- .../multiplayer/networking/quickstart.md | 2 +- .../client-methods/receive-message.md | 20 +- .../receive-subscription-change-message.md | 30 +- .../real-time-messages/overview.md | 39 ++ .../server-methods/add-entity-to-session.md | 16 +- .../server-methods/end-session.md | 16 +- .../remove-entity-from-session.md | 16 +- .../start-or-recover-session.md | 16 +- .../signalr-hub.md | 46 +- .../subscribing-to-resources.md | 22 +- .../toc.yml | 0 .../types/end-session-request.md | 40 ++ .../types/end-session-response.md | 20 +- .../types/message.md | 20 +- .../types/response-status.md | 16 +- .../types/shared-session-request.md | 20 +- .../types/shared-session-response.md | 20 +- .../types/start-or-recover-session-request.md | 20 +- .../start-or-recover-session-response.md | 22 +- .../types/subscription-change-message.md | 20 +- .../real-time-notifications/overview.md | 41 -- .../types/end-session-request.md | 42 -- .../player-progression/game-saves/linking.md | 395 ++++++++++++++++++ .../game-saves/media/mermaid-learn.json | 17 + .../game-saves/media/strategy2-flow.mmd | 44 ++ .../game-saves/media/strategy2-flow.svg | 1 + .../player-progression/game-saves/toc.yml | 2 + playfab-docs/pricing/Meters/meters.md | 4 +- playfab-docs/release-notes/2016.md | 8 +- playfab-docs/release-notes/index.md | 10 + 70 files changed, 1687 insertions(+), 343 deletions(-) create mode 100644 playfab-docs/api-references/events/Experimentation/exclusion-group-created.md create mode 100644 playfab-docs/api-references/events/Experimentation/exclusion-group-deleted.md create mode 100644 playfab-docs/api-references/events/Experimentation/exclusion-group-updated.md create mode 100644 playfab-docs/api-references/events/Experimentation/experiment-created.md create mode 100644 playfab-docs/api-references/events/Experimentation/experiment-deleted.md create mode 100644 playfab-docs/api-references/events/Experimentation/experiment-start-requested.md create mode 100644 playfab-docs/api-references/events/Experimentation/experiment-stop-requested.md create mode 100644 playfab-docs/api-references/events/Experimentation/experiment-updated.md create mode 100644 playfab-docs/api-references/events/Experimentation/player-experiment-variants-changed.md create mode 100644 playfab-docs/api-references/events/PlayStream/action-executed.md create mode 100644 playfab-docs/api-references/events/PlayStream/action-failed.md create mode 100644 playfab-docs/api-references/events/Segmentation/api-operation.md create mode 100644 playfab-docs/api-references/events/Segmentation/segment-entered.md create mode 100644 playfab-docs/api-references/events/Segmentation/segment-exited.md create mode 100644 playfab-docs/api-references/events/TargetedConfiguration/player-churn-prediction-changed.md create mode 100644 playfab-docs/api-references/events/data-types/actioneventdetails.md create mode 100644 playfab-docs/api-references/events/data-types/actionfailure.md create mode 100644 playfab-docs/api-references/events/data-types/actionresultdetails.md create mode 100644 playfab-docs/api-references/events/data-types/actiontrigger.md create mode 100644 playfab-docs/api-references/events/data-types/actiontype.md create mode 100644 playfab-docs/api-references/events/data-types/churnrisklevel.md create mode 100644 playfab-docs/api-references/events/data-types/experiment.md create mode 100644 playfab-docs/api-references/events/data-types/experimentrequestorigin.md create mode 100644 playfab-docs/api-references/events/data-types/experimentvariable.md create mode 100644 playfab-docs/api-references/events/data-types/experimentvariant.md create mode 100644 playfab-docs/api-references/events/data-types/segmentoperation.md create mode 100644 playfab-docs/api-references/events/data-types/segmentoperationstatus.md rename playfab-docs/multiplayer/lobby/{lobby-and-matchmaking-real-time-notifications.md => lobby-and-matchmaking-real-time-messages.md} (52%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/client-methods/receive-message.md (55%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/client-methods/receive-subscription-change-message.md (53%) create mode 100644 playfab-docs/multiplayer/real-time-messages/overview.md rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/server-methods/add-entity-to-session.md (64%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/server-methods/end-session.md (56%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/server-methods/remove-entity-from-session.md (61%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/server-methods/start-or-recover-session.md (64%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/signalr-hub.md (73%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/subscribing-to-resources.md (65%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/toc.yml (100%) create mode 100644 playfab-docs/multiplayer/real-time-messages/types/end-session-request.md rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/types/end-session-response.md (54%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/types/message.md (73%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/types/response-status.md (74%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/types/shared-session-request.md (65%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/types/shared-session-response.md (61%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/types/start-or-recover-session-request.md (61%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/types/start-or-recover-session-response.md (73%) rename playfab-docs/multiplayer/{real-time-notifications => real-time-messages}/types/subscription-change-message.md (80%) delete mode 100644 playfab-docs/multiplayer/real-time-notifications/overview.md delete mode 100644 playfab-docs/multiplayer/real-time-notifications/types/end-session-request.md create mode 100644 playfab-docs/player-progression/game-saves/linking.md create mode 100644 playfab-docs/player-progression/game-saves/media/mermaid-learn.json create mode 100644 playfab-docs/player-progression/game-saves/media/strategy2-flow.mmd create mode 100644 playfab-docs/player-progression/game-saves/media/strategy2-flow.svg diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index a88c70d12..0e982c4ae 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -1,6 +1,11 @@ { "redirections": [ { + "source_path": "playfab-docs/api-references/events/player-action-executed.md", + "redirect_url": "/gaming/playfab/api-references/events/playstream/player-action-executed", + "redirect_document_id": true + }, + { "source_path": "playfab-docs/sdks/objective-c/quickstart.md", "redirect_url": "/gaming/playfab/sdks/c/quickstart-ios", "redirect_document_id": false @@ -217,57 +222,57 @@ }, { "source_path": "playfab-docs/api-references/events/gamelobby-ended.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/gamelobby-started.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/gameserverhost-started.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/gameserverhost-stopped.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/player-joined-lobby.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/player-left-lobby.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/player-matched-with-lobby.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/session-ended.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/session-started.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/title-game-build-added.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { "source_path": "playfab-docs/api-references/events/title-game-build-modified.md", - "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/features/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { @@ -1065,7 +1070,7 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/server-methods/add-entity-to-session.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/server-methods/add-entity-to-session", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/server-methods/add-entity-to-session", "redirect_document_id": false }, { @@ -1580,17 +1585,17 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/types/end-session-request.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/types/end-session-request", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/end-session-request", "redirect_document_id": false }, { "source_path": "playfab-docs/features/real-time-notifications/types/end-session-response.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/types/end-session-response", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/end-session-response", "redirect_document_id": false }, { "source_path": "playfab-docs/features/real-time-notifications/server-methods/end-session.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/server-methods/end-session", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/server-methods/end-session", "redirect_document_id": false }, { @@ -2025,7 +2030,7 @@ }, { "source_path": "playfab-docs/features/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md", - "redirect_url": "/gaming/playfab/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications", + "redirect_url": "/gaming/playfab/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", "redirect_document_id": false }, { @@ -2275,7 +2280,7 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/types/message.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/types/message", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/message", "redirect_document_id": false }, { @@ -5365,12 +5370,12 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/client-methods/receive-message.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/client-methods/receive-message", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/client-methods/receive-message", "redirect_document_id": false }, { "source_path": "playfab-docs/features/real-time-notifications/client-methods/receive-subscription-change-message.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/client-methods/receive-subscription-change-message", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/client-methods/receive-subscription-change-message", "redirect_document_id": false }, { @@ -5395,7 +5400,7 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/server-methods/remove-entity-from-session.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/server-methods/remove-entity-from-session", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/server-methods/remove-entity-from-session", "redirect_document_id": false }, { @@ -5405,7 +5410,7 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/types/response-status.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/types/response-status", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/response-status", "redirect_document_id": false }, { @@ -5575,17 +5580,17 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/types/shared-session-request.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/types/shared-session-request", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/shared-session-request", "redirect_document_id": false }, { "source_path": "playfab-docs/features/real-time-notifications/types/shared-session-response.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/types/shared-session-response", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/shared-session-response", "redirect_document_id": false }, { "source_path": "playfab-docs/features/real-time-notifications/signalr-hub.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/signalr-hub", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/signalr-hub", "redirect_document_id": false }, { @@ -5600,17 +5605,17 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/types/start-or-recover-session-request.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/types/start-or-recover-session-request", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/start-or-recover-session-request", "redirect_document_id": false }, { "source_path": "playfab-docs/features/real-time-notifications/types/start-or-recover-session-response.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/types/start-or-recover-session-response", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/start-or-recover-session-response", "redirect_document_id": false }, { "source_path": "playfab-docs/features/real-time-notifications/server-methods/start-or-recover-session.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/server-methods/start-or-recover-session", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/server-methods/start-or-recover-session", "redirect_document_id": false }, { @@ -5650,12 +5655,12 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/subscribing-to-resources.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/subscribing-to-resources", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/subscribing-to-resources", "redirect_document_id": false }, { "source_path": "playfab-docs/features/real-time-notifications/types/subscription-change-message.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/types/subscription-change-message", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/subscription-change-message", "redirect_document_id": false }, { @@ -6790,7 +6795,7 @@ }, { "source_path": "features/multiplayer/lobby/notifications-overview.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/overview.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/overview", "redirect_document_id": false }, { @@ -6805,7 +6810,7 @@ }, { "source_path": "playfab-docs/features/real-time-notifications/overview.md", - "redirect_url": "/gaming/playfab/multiplayer/real-time-notifications/overview", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/overview", "redirect_document_id": false }, { @@ -6862,6 +6867,101 @@ "source_path": "playfab-docs/features/economy/index.yml", "redirect_url": "/gaming/playfab/economy-monetization/", "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/overview.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/overview", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/signalr-hub.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/signalr-hub", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/subscribing-to-resources.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/subscribing-to-resources", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/client-methods/receive-message.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/client-methods/receive-message", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/client-methods/receive-subscription-change-message.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/client-methods/receive-subscription-change-message", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/server-methods/start-or-recover-session.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/server-methods/start-or-recover-session", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/server-methods/end-session.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/server-methods/end-session", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/server-methods/add-entity-to-session.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/server-methods/add-entity-to-session", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/server-methods/remove-entity-from-session.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/server-methods/remove-entity-from-session", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/types/message.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/message", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/types/subscription-change-message.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/subscription-change-message", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/types/response-status.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/response-status", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/types/start-or-recover-session-request.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/start-or-recover-session-request", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/types/start-or-recover-session-response.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/start-or-recover-session-response", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/types/end-session-request.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/end-session-request", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/types/end-session-response.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/end-session-response", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/types/shared-session-request.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/shared-session-request", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/real-time-notifications/types/shared-session-response.md", + "redirect_url": "/gaming/playfab/multiplayer/real-time-messages/types/shared-session-response", + "redirect_document_id": false + }, + { + "source_path": "playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md", + "redirect_url": "/gaming/playfab/multiplayer/lobby/lobby-and-matchmaking-real-time-messages", + "redirect_document_id": false } ] } diff --git a/playfab-docs/api-references/events/Experimentation/exclusion-group-created.md b/playfab-docs/api-references/events/Experimentation/exclusion-group-created.md new file mode 100644 index 000000000..e0648f95c --- /dev/null +++ b/playfab-docs/api-references/events/Experimentation/exclusion-group-created.md @@ -0,0 +1,27 @@ +--- +title: exclusion_group_created +author: joelku +description: exclusion_group_created event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# exclusion_group_created + +This event is triggered when an exclusion group is created. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The unique identifier of the exclusion group.| +|Name|String|Friendly name of the exclusion group.| +|Description|String|Description of the exclusion group.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Experimentation/exclusion-group-deleted.md b/playfab-docs/api-references/events/Experimentation/exclusion-group-deleted.md new file mode 100644 index 000000000..0eddc7b9f --- /dev/null +++ b/playfab-docs/api-references/events/Experimentation/exclusion-group-deleted.md @@ -0,0 +1,25 @@ +--- +title: exclusion_group_deleted +author: joelku +description: exclusion_group_deleted event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# exclusion_group_deleted + +This event is triggered when an exclusion group is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The unique identifier of the exclusion group.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Experimentation/exclusion-group-updated.md b/playfab-docs/api-references/events/Experimentation/exclusion-group-updated.md new file mode 100644 index 000000000..2e4eb7a74 --- /dev/null +++ b/playfab-docs/api-references/events/Experimentation/exclusion-group-updated.md @@ -0,0 +1,27 @@ +--- +title: exclusion_group_updated +author: joelku +description: exclusion_group_updated event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# exclusion_group_updated + +This event is triggered when an exclusion group is updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The unique identifier of the exclusion group.| +|Name|String|Friendly name of the exclusion group.| +|Description|String|Description of the exclusion group.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Experimentation/experiment-created.md b/playfab-docs/api-references/events/Experimentation/experiment-created.md new file mode 100644 index 000000000..4c1050afd --- /dev/null +++ b/playfab-docs/api-references/events/Experimentation/experiment-created.md @@ -0,0 +1,29 @@ +--- +title: experiment_created +author: joelku +description: experiment_created event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# experiment_created + +This event is triggered when an experiment is created. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The unique identifier of the experiment.| +|Name|String|The friendly name of the experiment.| +|UsesOverrides|Boolean|Specifies whether the experiment uses title data overrides.| +|UsesExclusionGroup|Boolean|Specifies whether the experiment uses an exclusion group.| +|Experiment|[Experiment](../data-types/experiment.md)|The experiment configuration payload.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Experimentation/experiment-deleted.md b/playfab-docs/api-references/events/Experimentation/experiment-deleted.md new file mode 100644 index 000000000..85ff9eb78 --- /dev/null +++ b/playfab-docs/api-references/events/Experimentation/experiment-deleted.md @@ -0,0 +1,26 @@ +--- +title: experiment_deleted +author: joelku +description: experiment_deleted event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# experiment_deleted + +This event is triggered when an experiment is deleted. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The unique identifier of the experiment.| +|Name|String|The friendly name of the experiment.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Experimentation/experiment-start-requested.md b/playfab-docs/api-references/events/Experimentation/experiment-start-requested.md new file mode 100644 index 000000000..337d0c305 --- /dev/null +++ b/playfab-docs/api-references/events/Experimentation/experiment-start-requested.md @@ -0,0 +1,30 @@ +--- +title: experiment_start_requested +author: joelku +description: experiment_start_requested event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# experiment_start_requested + +This event is triggered when an experiment is requested to start. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The unique identifier of the experiment.| +|Name|String|The friendly name of the experiment.| +|UsesOverrides|Boolean|Specifies whether the experiment uses title data overrides.| +|UsesExclusionGroup|Boolean|Specifies whether the experiment uses an exclusion group.| +|RequestOrigin|[ExperimentRequestOrigin](../data-types/experimentrequestorigin.md)|The origin of the request to start the experiment.| +|Experiment|[Experiment](../data-types/experiment.md)|The experiment configuration payload.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Experimentation/experiment-stop-requested.md b/playfab-docs/api-references/events/Experimentation/experiment-stop-requested.md new file mode 100644 index 000000000..df990f6ed --- /dev/null +++ b/playfab-docs/api-references/events/Experimentation/experiment-stop-requested.md @@ -0,0 +1,27 @@ +--- +title: experiment_stop_requested +author: joelku +description: experiment_stop_requested event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# experiment_stop_requested + +This event is triggered when an experiment is requested to stop. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The unique identifier of the experiment.| +|Name|String|The friendly name of the experiment.| +|RequestOrigin|[ExperimentRequestOrigin](../data-types/experimentrequestorigin.md)|The origin of the request to stop the experiment.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Experimentation/experiment-updated.md b/playfab-docs/api-references/events/Experimentation/experiment-updated.md new file mode 100644 index 000000000..ecaaef18c --- /dev/null +++ b/playfab-docs/api-references/events/Experimentation/experiment-updated.md @@ -0,0 +1,29 @@ +--- +title: experiment_updated +author: joelku +description: experiment_updated event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# experiment_updated + +This event is triggered when an experiment is updated. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The unique identifier of the experiment.| +|Name|String|The friendly name of the experiment.| +|UsesOverrides|Boolean|Specifies whether the experiment uses title data overrides.| +|UsesExclusionGroup|Boolean|Specifies whether the experiment uses an exclusion group.| +|Experiment|[Experiment](../data-types/experiment.md)|The experiment configuration payload.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/Experimentation/player-experiment-variants-changed.md b/playfab-docs/api-references/events/Experimentation/player-experiment-variants-changed.md new file mode 100644 index 000000000..d96ab8827 --- /dev/null +++ b/playfab-docs/api-references/events/Experimentation/player-experiment-variants-changed.md @@ -0,0 +1,26 @@ +--- +title: player_experiment_variants_changed +author: joelku +description: player_experiment_variants_changed event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_experiment_variants_changed + +This event is triggered when a player's set of experiment variants is changed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|PreviousExperimentVariants|String[]|Previous experiment variant list.| +|ExperimentVariants|String[]|New experiment variant list.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] \ No newline at end of file diff --git a/playfab-docs/api-references/events/PlayStream/action-executed.md b/playfab-docs/api-references/events/PlayStream/action-executed.md new file mode 100644 index 000000000..4de21e18f --- /dev/null +++ b/playfab-docs/api-references/events/PlayStream/action-executed.md @@ -0,0 +1,27 @@ +--- +title: action_executed +author: joelku +description: action_executed event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# action_executed + +This event is emitted when an action is executed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Data|[ActionResultDetails](../data-types/actionresultdetails.md)|The result of the action.| +|Trigger|[ActionTrigger](../data-types/actiontrigger.md)|Information about the trigger that initiated the action.| +|EventDetails|[ActionEventDetails](../data-types/actioneventdetails.md)|Information about the event that triggered the action.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/PlayStream/action-failed.md b/playfab-docs/api-references/events/PlayStream/action-failed.md new file mode 100644 index 000000000..be1b4102d --- /dev/null +++ b/playfab-docs/api-references/events/PlayStream/action-failed.md @@ -0,0 +1,27 @@ +--- +title: action_failed +author: joelku +description: action_failed event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# action_failed + +This event is emitted when an action failed to execute. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Error|[ActionFailure](../data-types/actionfailure.md)|Information about the error that occurred during execution.| +|Trigger|[ActionTrigger](../data-types/actiontrigger.md)|Information about the trigger that initiated the action.| +|EventDetails|[ActionEventDetails](../data-types/actioneventdetails.md)|Information about the event that triggered the action.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Player/player-action-executed.md b/playfab-docs/api-references/events/Player/player-action-executed.md index 34ce3707a..f90fa1a56 100644 --- a/playfab-docs/api-references/events/Player/player-action-executed.md +++ b/playfab-docs/api-references/events/Player/player-action-executed.md @@ -3,7 +3,7 @@ title: player_action_executed author: joannaleecy description: player_action_executed event. ms.author: jenelleb -ms.date: 02/19/2019 +ms.date: 02/19/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, playstream events @@ -14,7 +14,7 @@ ms.localizationpriority: medium This event is triggered when an action linked to a segmentation change or event rule executes on a player. -Properties +## Properties |Name|Type|Description| | :--------------------|:-------------------|:----------------------| diff --git a/playfab-docs/api-references/events/Segmentation/api-operation.md b/playfab-docs/api-references/events/Segmentation/api-operation.md new file mode 100644 index 000000000..3587cf341 --- /dev/null +++ b/playfab-docs/api-references/events/Segmentation/api-operation.md @@ -0,0 +1,33 @@ +--- +title: api_operation +author: joelku +description: api_operation event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# api_operation + +This event is triggered to summarize the actions taken during an invocation of the segmentation CRUD API. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Created|DateTime|The date and time when the operation was submitted.| +|Completed|DateTime|The date and time when the operation was completed.| +|Operation|[SegmentOperation](../data-types/segmentoperation.md)|The segment operation that was performed.| +|OperationStatus|[SegmentOperationStatus](../data-types/segmentoperationstatus.md)|The status of the operation.| +|SegmentId|String|The ID of the segment.| +|SegmentName|String|The name of the segment.| +|SegmentDefinition|String|The segment definition.| +|EnteredSegmentActions|String|The actions triggered when a profile enters the segment.| +|LeftSegmentActions|String|The actions triggered when a profile exits the segment.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Segmentation/segment-entered.md b/playfab-docs/api-references/events/Segmentation/segment-entered.md new file mode 100644 index 000000000..c06460d3e --- /dev/null +++ b/playfab-docs/api-references/events/Segmentation/segment-entered.md @@ -0,0 +1,26 @@ +--- +title: segment_entered +author: joelku +description: segment_entered event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# segment_entered + +This event is triggered when a profile enters a segment. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|SegmentId|String|The ID of the segment that had a status change.| +|SegmentName|String|The friendly name of the segment.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/Segmentation/segment-exited.md b/playfab-docs/api-references/events/Segmentation/segment-exited.md new file mode 100644 index 000000000..5e9eb3e0d --- /dev/null +++ b/playfab-docs/api-references/events/Segmentation/segment-exited.md @@ -0,0 +1,26 @@ +--- +title: segment_exited +author: joelku +description: segment_exited event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# segment_exited + +This event is triggered when a profile exits a segment. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|SegmentId|String|The ID of the segment that had a status change.| +|SegmentName|String|The friendly name of the segment.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv2.md)] diff --git a/playfab-docs/api-references/events/TargetedConfiguration/player-churn-prediction-changed.md b/playfab-docs/api-references/events/TargetedConfiguration/player-churn-prediction-changed.md new file mode 100644 index 000000000..110eda25a --- /dev/null +++ b/playfab-docs/api-references/events/TargetedConfiguration/player-churn-prediction-changed.md @@ -0,0 +1,25 @@ +--- +title: player_churn_prediction_changed +author: joelku +description: player_churn_prediction_changed event. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# player_churn_prediction_changed + +This event is triggered when a player's churn prediction is changed. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ChurnPrediction|[ChurnRiskLevel](../data-types/churnrisklevel.md)|New churn prediction value.| + +## Common Properties + +[!INCLUDE [common-properties](../../../includes/_common-properties-eventsv1.md)] diff --git a/playfab-docs/api-references/events/data-types/actioneventdetails.md b/playfab-docs/api-references/events/data-types/actioneventdetails.md new file mode 100644 index 000000000..269f477ec --- /dev/null +++ b/playfab-docs/api-references/events/data-types/actioneventdetails.md @@ -0,0 +1,23 @@ +--- +title: ActionEventDetails +author: joelku +description: ActionEventDetails data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ActionEventDetails + +Information about the event that triggered the action. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The ID of the triggering event.| +|FullName|[FullNameObject](fullnameobject.md)|The fully qualified name of the triggering event.| +|Timestamp|DateTime|The server timestamp of the triggering event.| diff --git a/playfab-docs/api-references/events/data-types/actionfailure.md b/playfab-docs/api-references/events/data-types/actionfailure.md new file mode 100644 index 000000000..25948e36b --- /dev/null +++ b/playfab-docs/api-references/events/data-types/actionfailure.md @@ -0,0 +1,22 @@ +--- +title: ActionFailure +author: joelku +description: ActionFailure data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ActionFailure + +Information about the error that occurred during action execution. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|FriendlyMessage|String|The friendly message of the action failure.| +|ErrorCode|int32|The error code of the failure.| diff --git a/playfab-docs/api-references/events/data-types/actionresultdetails.md b/playfab-docs/api-references/events/data-types/actionresultdetails.md new file mode 100644 index 000000000..e3d3f051f --- /dev/null +++ b/playfab-docs/api-references/events/data-types/actionresultdetails.md @@ -0,0 +1,22 @@ +--- +title: ActionResultDetails +author: joelku +description: ActionResultDetails data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ActionResultDetails + +The result of an action, if it succeeded. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|ActionResult|object|The result of the action.| +|FriendlyResult|String|The friendly message of the result.| diff --git a/playfab-docs/api-references/events/data-types/actiontrigger.md b/playfab-docs/api-references/events/data-types/actiontrigger.md new file mode 100644 index 000000000..d83f91a85 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/actiontrigger.md @@ -0,0 +1,27 @@ +--- +title: ActionTrigger +author: joelku +description: ActionTrigger data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ActionTrigger + +Information about the trigger that initiated the action. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|RuleId|String|The ID of the rule that triggered the action.| +|RuleName|String|The friendly name of the rule that triggered the action.| +|Timestamp|DateTime|The server time when the rule was evaluated.| +|ActionIndex|int32|The position of the action within the rule, starting from 0.| +|ActionId|String|The ID of the action.| +|ActionName|String|The friendly name of the action.| +|ActionType|[ActionType](actiontype.md)|The type of the action.| diff --git a/playfab-docs/api-references/events/data-types/actiontype.md b/playfab-docs/api-references/events/data-types/actiontype.md new file mode 100644 index 000000000..6e5cdceaf --- /dev/null +++ b/playfab-docs/api-references/events/data-types/actiontype.md @@ -0,0 +1,31 @@ +--- +title: ActionType +author: joelku +description: ActionType data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ActionType + +The possible types of actions. + +## Values + +|Value|Description| +| :--------------------|:----------------------| +|ExecuteFunction|Execute an Azure Function.| +|AddVirtualCurrencies|Add virtual currencies.| +|GrantInventoryItems|Grant inventory items.| +|SendEntityPushNotification|Send an entity push notification.| +|SendEntityEmail|Send an entity email.| +|ExecuteEntityCloudScript|Execute entity CloudScript.| +|UpdatePlayerCustomProperties|Update player custom properties.| +|DeletePlayerCustomProperties|Delete player custom properties.| +|AddInventoryItemsV2|Add inventory items (V2).| +|SubtractInventoryItemsV2|Subtract inventory items (V2).| +|DeleteInventoryItemsV2|Delete inventory items (V2).| diff --git a/playfab-docs/api-references/events/data-types/churnrisklevel.md b/playfab-docs/api-references/events/data-types/churnrisklevel.md new file mode 100644 index 000000000..8e00d2efa --- /dev/null +++ b/playfab-docs/api-references/events/data-types/churnrisklevel.md @@ -0,0 +1,24 @@ +--- +title: ChurnRiskLevel +author: joelku +description: ChurnRiskLevel data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ChurnRiskLevel + +Defines values for the churn risk level of a player. + +## Values + +|Value|Description| +| :--------------------|:----------------------| +|NoData|Not enough data to make a prediction.| +|LowRisk|The player has a low risk of churning.| +|MediumRisk|The player has a medium risk of churning.| +|HighRisk|The player has a high risk of churning.| diff --git a/playfab-docs/api-references/events/data-types/experiment.md b/playfab-docs/api-references/events/data-types/experiment.md new file mode 100644 index 000000000..aa64d7bbe --- /dev/null +++ b/playfab-docs/api-references/events/data-types/experiment.md @@ -0,0 +1,26 @@ +--- +title: Experiment +author: joelku +description: Experiment data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# Experiment + +Payload representing updates to experiment configuration. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|StartTime|DateTime|When the experiment should start or was started.| +|DurationInDays|int32|The duration of the experiment in days.| +|SegmentId|String|The ID of the segment to which this experiment applies.| +|ExclusionGroupId|String|The ID of the exclusion group to which this experiment applies.| +|ExclusionGroupTrafficAllocation|int32|Percentage of exclusion-group traffic seen by this experiment.| +|Variants|[ExperimentVariant](experimentvariant.md)[]|List of variants for the experiment.| diff --git a/playfab-docs/api-references/events/data-types/experimentrequestorigin.md b/playfab-docs/api-references/events/data-types/experimentrequestorigin.md new file mode 100644 index 000000000..24ccb6223 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/experimentrequestorigin.md @@ -0,0 +1,22 @@ +--- +title: ExperimentRequestOrigin +author: joelku +description: ExperimentRequestOrigin data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ExperimentRequestOrigin + +The set of origins from which experiment requests can be issued. + +## Values + +|Value|Description| +| :--------------------|:----------------------| +|Scheduled|The request was issued by a scheduled process.| +|Manual|The request was issued manually.| diff --git a/playfab-docs/api-references/events/data-types/experimentvariable.md b/playfab-docs/api-references/events/data-types/experimentvariable.md new file mode 100644 index 000000000..5333cd74d --- /dev/null +++ b/playfab-docs/api-references/events/data-types/experimentvariable.md @@ -0,0 +1,22 @@ +--- +title: ExperimentVariable +author: joelku +description: ExperimentVariable data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ExperimentVariable + +A variable (key-value pair) within an experiment variant. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Name|String|Name of the variable.| +|Value|String|Value of the variable.| diff --git a/playfab-docs/api-references/events/data-types/experimentvariant.md b/playfab-docs/api-references/events/data-types/experimentvariant.md new file mode 100644 index 000000000..8e73dbd54 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/experimentvariant.md @@ -0,0 +1,26 @@ +--- +title: ExperimentVariant +author: joelku +description: ExperimentVariant data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# ExperimentVariant + +A variant within an experiment. + +## Properties + +|Name|Type|Description| +| :--------------------|:-------------------|:----------------------| +|Id|String|The unique identifier of the variant.| +|Name|String|The name of the variant.| +|TrafficPercentage|int32|The percentage (0 to 100) of players in the experiment that will see this variant.| +|IsControl|Boolean|Specifies if variant is the control for the experiment.| +|TitleDataOverrideLabel|String|The title data override label.| +|Variables|[ExperimentVariable](experimentvariable.md)[]|The variables returned by this variant.| diff --git a/playfab-docs/api-references/events/data-types/segmentoperation.md b/playfab-docs/api-references/events/data-types/segmentoperation.md new file mode 100644 index 000000000..61cb82436 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/segmentoperation.md @@ -0,0 +1,24 @@ +--- +title: SegmentOperation +author: joelku +description: SegmentOperation data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# SegmentOperation + +The type of segment operation that was performed. + +## Values + +|Value|Description| +| :--------------------|:----------------------| +|LookUp|A segment lookup operation.| +|Create|A segment creation operation.| +|Delete|A segment deletion operation.| +|Update|A segment update operation.| diff --git a/playfab-docs/api-references/events/data-types/segmentoperationstatus.md b/playfab-docs/api-references/events/data-types/segmentoperationstatus.md new file mode 100644 index 000000000..ce31ab831 --- /dev/null +++ b/playfab-docs/api-references/events/data-types/segmentoperationstatus.md @@ -0,0 +1,24 @@ +--- +title: SegmentOperationStatus +author: joelku +description: SegmentOperationStatus data type. +ms.author: joelku +ms.date: 02/19/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, playstream events +ms.localizationpriority: medium +--- + +# SegmentOperationStatus + +The status of a segment operation. + +## Values + +|Value|Description| +| :--------------------|:----------------------| +|Start|The operation has started.| +|Success|The operation completed successfully.| +|Failed|The operation failed.| +|ValidationError|The operation failed due to a validation error.| diff --git a/playfab-docs/api-references/events/index.md b/playfab-docs/api-references/events/index.md index 116d89d00..a8181cde3 100644 --- a/playfab-docs/api-references/events/index.md +++ b/playfab-docs/api-references/events/index.md @@ -83,6 +83,36 @@ Each event type has a set of properties that are included as part of event's dat - [studio_user_removed](DeveloperIdentity/studio-user-removed.md) This event is triggered when a user is removed from a studio. +## Experimentation + +- [exclusion_group_created](Experimentation/exclusion-group-created.md) + This event is triggered when an exclusion group is created. + +- [exclusion_group_deleted](Experimentation/exclusion-group-deleted.md) + This event is triggered when an exclusion group is deleted. + +- [exclusion_group_updated](Experimentation/exclusion-group-updated.md) + This event is triggered when an exclusion group is updated. + +- [experiment_created](Experimentation/experiment-created.md) + This event is triggered when an experiment is created. + +- [experiment_deleted](Experimentation/experiment-deleted.md) + This event is triggered when an experiment is deleted. + +- [experiment_start_requested](Experimentation/experiment-start-requested.md) + This event is triggered when an experiment start is requested. + +- [experiment_stop_requested](Experimentation/experiment-stop-requested.md) + This event is triggered when an experiment stop is requested. + +- [experiment_updated](Experimentation/experiment-updated.md) + This event is triggered when an experiment is updated. + +- [player_experiment_variants_changed](Experimentation/player-experiment-variants-changed.md) + This event is triggered when a player's experiment variants are changed. + + ## Extension - [title_aborted_task](Extension/title-aborted-task.md) @@ -243,7 +273,7 @@ Each event type has a set of properties that are included as part of event's dat This event is triggered when a multiplayer server build is deleted. - [build_region_status_changed](MultiplayerServers/build-region-status-changed.md) - This event is triggered when a multiplayer server's build region status is changed. + This event is triggered when a multiplayer server build region status is changed. - [build_region_updated](MultiplayerServers/build-region-updated.md) This event is triggered when a multiplayer server build region is updated. @@ -615,6 +645,25 @@ Each event type has a set of properties that are included as part of event's dat - [objects_updated](PlayerProfile/objects-updated.md) This event is triggered when objects are updated. +## PlayStream + +- [action_executed](PlayStream/action-executed.md) + This event is emitted when an action is executed. + +- [action_failed](PlayStream/action-failed.md) + This event is emitted when an action failed to execute. + +## Segmentation + +- [segment_entered](Segmentation/segment-entered.md) + This event is triggered when a profile enters a segment. + +- [segment_exited](Segmentation/segment-exited.md) + This event is triggered when a profile exits a segment. + +- [api_operation](Segmentation/api-operation.md) + This event is triggered to summarize the actions taken during an invocation of the segmentation CRUD API. + ## Session - [client_focus_change](Session/client-focus-change.md) @@ -657,6 +706,11 @@ Each event type has a set of properties that are included as part of event's dat - [title_deactivated](TitleData/title-deactivated.md) This event is triggered when a title is deactivated. +## TargetedConfiguration + +- [player_churn_prediction_changed](TargetedConfiguration/player-churn-prediction-changed.md) + This event is triggered when a player's churn prediction is changed. + ## Statistics - [statistic_updated](Statistics/statistic-updated.md) diff --git a/playfab-docs/api-references/toc.yml b/playfab-docs/api-references/toc.yml index 36dc3f475..0e1c66245 100644 --- a/playfab-docs/api-references/toc.yml +++ b/playfab-docs/api-references/toc.yml @@ -4,8 +4,8 @@ href: index.md - name: Reference href: /rest/api/playfab/admin/ - - name: Real-time notifications for Lobby and Matchmaking - href: ../multiplayer/real-time-notifications/toc.yml + - name: Real-time messages for Lobby and Matchmaking + href: ../multiplayer/real-time-messages/toc.yml - name: Services C API href: c/toc.yml - name: Party C/C++ API @@ -90,6 +90,26 @@ href: events/Extension/title-updated-task.md - name: export_completed href: events/Extension/export-completed.md + - name: Experimentation + items: + - name: exclusion_group_created + href: events/Experimentation/exclusion-group-created.md + - name: exclusion_group_deleted + href: events/Experimentation/exclusion-group-deleted.md + - name: exclusion_group_updated + href: events/Experimentation/exclusion-group-updated.md + - name: experiment_created + href: events/Experimentation/experiment-created.md + - name: experiment_deleted + href: events/Experimentation/experiment-deleted.md + - name: experiment_start_requested + href: events/Experimentation/experiment-start-requested.md + - name: experiment_stop_requested + href: events/Experimentation/experiment-stop-requested.md + - name: experiment_updated + href: events/Experimentation/experiment-updated.md + - name: player_experiment_variants_changed + href: events/Experimentation/player-experiment-variants-changed.md - name: Functions items: - name: function_executed @@ -402,6 +422,20 @@ href: events/PlayerProfile/language-updated.md - name: objects_updated href: events/PlayerProfile/objects-updated.md + - name: PlayStream + items: + - name: action_executed + href: events/PlayStream/action-executed.md + - name: action_failed + href: events/PlayStream/action-failed.md + - name: Segmentation + items: + - name: api_operation + href: events/Segmentation/api-operation.md + - name: segment_entered + href: events/Segmentation/segment-entered.md + - name: segment_exited + href: events/Segmentation/segment-exited.md - name: Session items: - name: client_focus_change @@ -432,6 +466,10 @@ href: events/TitleData/title-data-updated.md - name: title_deactivated href: events/TitleData/title-deactivated.md + - name: TargetedConfiguration + items: + - name: player_churn_prediction_changed + href: events/TargetedConfiguration/player-churn-prediction-changed.md - name: Statistics items: - name: statistic_updated diff --git a/playfab-docs/identity/player-identity/platform-specific-authentication/google-html5.md b/playfab-docs/identity/player-identity/platform-specific-authentication/google-html5.md index 5a3965dd4..9024daf55 100644 --- a/playfab-docs/identity/player-identity/platform-specific-authentication/google-html5.md +++ b/playfab-docs/identity/player-identity/platform-specific-authentication/google-html5.md @@ -233,7 +233,7 @@ In this example, we show how to test the LoginWithGoogleAccount API using the cl ``` -Remember to open this page using your web server, and make sure to access this page using the URL you specified, while configuring Google Project, ([PlayFab](http://playfab.example) in our case). +Remember to open this page using your web server, and make sure to access this page using the URL you specified, while configuring Google Project, (`http://playfab.example` in our case). 1. Once the page opens, select **G Signed In**, and follow the general Google authentication flow. 2. When this is finished, the script will try to authenticate on the PlayFab side and output the result. diff --git a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-client-sdk-errors.md b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-client-sdk-errors.md index c9813f349..e43fc92a0 100644 --- a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-client-sdk-errors.md +++ b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-client-sdk-errors.md @@ -6,7 +6,7 @@ ms.author: scmunro ms.date: 11/12/2022 ms.topic: article ms.service: azure-playfab -keywords: playfab, multiplayer, networking, lobby, matchmaking, async, state change, notification +keywords: playfab, multiplayer, networking, lobby, matchmaking, async, state change, message --- # Handling Lobby and Matchmaking SDK errors @@ -55,7 +55,7 @@ than synchronous errors. A non-exhaustive list of some of the types of errors re - service throttling errors - invalid parameter errors that can't be validated synchronously on the client -- errors interacting with the real-time notification service +- errors interacting with the real-time message service - connectivity errors See the [Error codes and error messages](#error-codes-and-error-messages) section for guidance on getting human-readable diff --git a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-messages.md similarity index 52% rename from playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md rename to playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-messages.md index 80ffe2473..582c48dcd 100644 --- a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md +++ b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking-real-time-messages.md @@ -1,43 +1,43 @@ --- author: thboard -title: Lobby and Matchmaking real-time Notifications -description: Conceptual overview for Match and Lobby notifications +title: Lobby and Matchmaking real-time messages +description: Conceptual overview for Match and Lobby messages ms.author: thboard ms.topic: conceptual ms.service: azure-playfab ms.date: 03/14/2022 --- -# Lobby and Matchmaking real-time notifications +# Lobby and Matchmaking real-time messages ## Overview The Matchmaking and Lobby features have built in support for real-time -notifications. Notifying players of changes to Matchmaking or Lobby has never -been easier, as the work to handle notifications is done for you in the [PlayFab Lobby and Matchmaking SDK](lobby-matchmaking-sdks/lobby-matchmaking-sdks.md). New APIs will -allow connected clients to subscribe for notifications of Lobby and Matchmaking +messages. Sending messages to players about changes to Matchmaking or Lobby has never +been easier, as the work to handle messages is done for you in the [PlayFab Lobby and Matchmaking SDK](lobby-matchmaking-sdks/lobby-matchmaking-sdks.md). New APIs will +allow connected clients to subscribe for messages about Lobby and Matchmaking changes. With this addition, you'll no longer need to poll for changes to matches or lobbies. The SDK has been designed to simplify your work. The SDK manages calls between game clients or servers and PlayFab Lobby and Matchmaking services. It handles -the delivery of notifications from those services to connected clients in real -time. Real-time notifications have cross-platform support, and will work +the delivery of messages from those services to connected clients in real +time. Real-time messages have cross-platform support, and will work anywhere PlayFab supplies a SDK. Matchmaking and Lobby can be used separately or -together, and real-time notifications will work in either case. There's no -support for real-time notifications without the SDK at this time. -Real-time notifications aren't available as a solution for stand-alone or +together, and real-time messages will work in either case. There's no +support for real-time messages without the SDK at this time. +Real-time messages aren't available as a solution for stand-alone or general use. -## How do real-time notifications work +## How do real-time messages work -Each client maintains a single WebSocket to receive real-time notifications. +Each client maintains a single WebSocket to receive real-time messages. When there are updates to Matchmaking or Lobby resources in the cloud, the -SDK will forward notifications in real-time to all connected clients +SDK will forward messages in real-time to all connected clients subscribed to those resources. -When a client connects to receive real-time notifications, they'll open a new -WebSocket connection to receive notifications and listen for change events. When +When a client connects to receive real-time messages, they'll open a new +WebSocket connection to receive messages and listen for change events. When a client creates a lobby, joins a lobby, starts listening for invitations, or creates a Matchmaking ticket, the connected client will subscribe to a Lobby or Matchmaking resource to listen for changes. The client will be notified when @@ -45,27 +45,27 @@ there's an update on the resource topic they’ve subscribed to. For example, if client has subscribed to a Lobby resource, they may be notified on change events like Player A or B has joined or left a Lobby. Matchmaking and Lobby documentation describe in more detail the operations that will power -notifications. +messages. -The WebSocket connection that enables real-time notifications is also used for +The WebSocket connection that enables real-time messages is also used for detecting client connectivity. This client connectivity status is used by the Lobby service to power lobby ownership management. ## Shared connection support -Matchmaking and Lobby notifications have support to share a single WebSocket +Matchmaking and Lobby messages have support to share a single WebSocket connection, which may be useful if you’re creating a title with couch co-op. Today, up to eight local users may share the WebSocket connection, and local players can be added or removed to that shared connection. Multiple users -sharing the same connection can subscribe to topics to get notifications for +sharing the same connection can subscribe to topics to get messages for Matchmaking or Lobby events for those topics. ## Using the SDK The SDK simplifies your work for cross-network and cross-platform play by -handling real-time notifications for you. Notifications are sent to clients on +handling real-time messages for you. Messages are sent to clients on receiving invites, joining and updating lobbies, finding matches, and more. The -SDK enables cross-platform play and real-time notifications on any -platform that PlayFab offers SDK support. Sending notifications to clients is +SDK enables cross-platform play and real-time messages on any +platform that PlayFab offers SDK support. Sending messages to clients is automatic, and the developer doesn't have to do any work to enable -notifications. +messages. diff --git a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md index d2301018a..82e027380 100644 --- a/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md +++ b/playfab-docs/multiplayer/lobby/lobby-matchmaking-sdks/lobby-and-matchmaking-release-notes.md @@ -162,7 +162,7 @@ February 11, 2025 ### Bug fixes -- Fixed an issue where the library would incorrectly retry some operations associated with the real-time notification service when HTTP 401 was received. +- Fixed an issue where the library would incorrectly retry some operations associated with the real-time message service when HTTP 401 was received. - Fixed a regression introduced in v1.7.8 that assigned the `PFMultiplayerServerDetails::region` value to `PFMultiplayerServerDetails::fqdn`. - Fixed an issue where the properties associated with a new member weren't immediately available until a subsequent `Updated` state change was provided. Now, as soon as a `MemberAdded` state change is provided to the game, [PFLobbyGetMemberConnectionStatus()](../playfabmultiplayerreference-cpp/pflobby/functions/pflobbygetmemberconnectionstatus.md), [PFLobbyGetMemberPropertyKeys()](../playfabmultiplayerreference-cpp/pflobby/functions/pflobbygetmemberpropertykeys.md), and [PFLobbyGetMemberProperty()](../playfabmultiplayerreference-cpp/pflobby/functions/pflobbygetmemberproperty.md) provide the most up-to-date information associated with the member. In order to preserve compatibility for games that took a dependency on the previous behavior, the first `Updated` state change after the member is added will continue to provide this initial list of property keys as if they were new properties. - Fixed a couple of issues where the library could crash when [PFMultiplayerUninitialize()](../playfabmultiplayerreference-cpp/pfmultiplayer/functions/pfmultiplayeruninitialize.md) was called while cleaning up internal web request resources. diff --git a/playfab-docs/multiplayer/lobby/toc.yml b/playfab-docs/multiplayer/lobby/toc.yml index 48bfa6670..b65438525 100644 --- a/playfab-docs/multiplayer/lobby/toc.yml +++ b/playfab-docs/multiplayer/lobby/toc.yml @@ -29,8 +29,8 @@ items: href: lobby-and-matchmaking-client-sdk-async.md - name: Handling C++ SDK errors href: lobby-and-matchmaking-client-sdk-errors.md -- name: Lobby and Matchmaking real-time notifications - href: lobby-and-matchmaking-real-time-notifications.md +- name: Lobby and Matchmaking real-time messages + href: lobby-and-matchmaking-real-time-messages.md - name: Reference items: - name: C++ SDK reference diff --git a/playfab-docs/multiplayer/matchmaking/backfill-tickets.md b/playfab-docs/multiplayer/matchmaking/backfill-tickets.md index f5530ef56..0e8b78533 100644 --- a/playfab-docs/multiplayer/matchmaking/backfill-tickets.md +++ b/playfab-docs/multiplayer/matchmaking/backfill-tickets.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Using server backfill tickets - REST API > [!NOTE] -> We highly recommend you consider using the Multiplayer SDKs as it includes real-time notification support that reduces the need for polling, improving the matchmaking experience and reducing delays. [Using Server Backfill Tickets - Multiplayer SDK](backfill-tickets-multiplayer-sdk.md) +> We highly recommend you consider using the Multiplayer SDKs as it includes real-time message support that reduces the need for polling, improving the matchmaking experience and reducing delays. [Using Server Backfill Tickets - Multiplayer SDK](backfill-tickets-multiplayer-sdk.md) Games hosted on a server sometimes find they need to search for extra players. Most often this occurs when one or more players disconnect while the diff --git a/playfab-docs/multiplayer/matchmaking/quickstart.md b/playfab-docs/multiplayer/matchmaking/quickstart.md index adb110b74..dad405ab4 100644 --- a/playfab-docs/multiplayer/matchmaking/quickstart.md +++ b/playfab-docs/multiplayer/matchmaking/quickstart.md @@ -13,7 +13,7 @@ ms.localizationpriority: medium # Matchmaking REST API quickstart > [!NOTE] -> We highly recommend you consider using the Multiplayer SDKs as it includes real-time notification support that reduces the need for polling. This will improve the matchmaking experience and reduce delays. [Quickstart - Client SDK](quickstart-client-sdk.md) +> We highly recommend you consider using the Multiplayer SDKs as it includes real-time message support that reduces the need for polling. This will improve the matchmaking experience and reduce delays. [Quickstart - Client SDK](quickstart-client-sdk.md) This quickstart guide walks you through the entire process for integrating the matchmaking feature. All code examples within this quickstart are for Unity - however, the concepts and flow apply (in general) to other platforms as well. @@ -79,7 +79,7 @@ PlayFabMultiplayerAPI.CreateMatchmakingTicket( ### Check the status of the matchmaking ticket -You must poll the service by `TicketId` to access the `Status` of the ticket in matchmaking. In order to do so, have your title call [GetMatchmakingTicket](xref:titleid.playfabapi.com.multiplayer.matchmaking.getmatchmakingticket). You can poll up to 10 times per minute. For instance, poll for the ticket status every 6 seconds. Polling can increase delays when retrieving the status of your ticket. It is for this reason we highly recommend you consider using the Multiplayer SDK method described here [Quickstart - Client SDK](quickstart-client-sdk.md). This avoids the need to poll by using the real-time notification functionality. +You must poll the service by `TicketId` to access the `Status` of the ticket in matchmaking. In order to do so, have your title call [GetMatchmakingTicket](xref:titleid.playfabapi.com.multiplayer.matchmaking.getmatchmakingticket). You can poll up to 10 times per minute. For instance, poll for the ticket status every 6 seconds. Polling can increase delays when retrieving the status of your ticket. It is for this reason we highly recommend you consider using the Multiplayer SDK method described here [Quickstart - Client SDK](quickstart-client-sdk.md). This avoids the need to poll by using the real-time message functionality. When the status of the ticket changes to `Matched`, your client can stop polling the ticket. From that point on, the ticket will include the `MatchId`. diff --git a/playfab-docs/multiplayer/matchmaking/toc.yml b/playfab-docs/multiplayer/matchmaking/toc.yml index 36af65398..829c2740e 100644 --- a/playfab-docs/multiplayer/matchmaking/toc.yml +++ b/playfab-docs/multiplayer/matchmaking/toc.yml @@ -31,8 +31,8 @@ items: href: ../lobby/lobby-and-matchmaking-client-sdk-async.md - name: Handling Client SDK errors href: ../lobby/lobby-and-matchmaking-client-sdk-errors.md -- name: Lobby and Matchmaking real-time notifications - href: ../lobby/lobby-and-matchmaking-real-time-notifications.md +- name: Lobby and Matchmaking real-time messages + href: ../lobby/lobby-and-matchmaking-real-time-messages.md - name: Reference items: - name: Client SDK reference diff --git a/playfab-docs/multiplayer/mpintro.md b/playfab-docs/multiplayer/mpintro.md index 8e2f76397..1a4357895 100644 --- a/playfab-docs/multiplayer/mpintro.md +++ b/playfab-docs/multiplayer/mpintro.md @@ -23,7 +23,7 @@ Multiplayer is a great addition to many titles, and PlayFab provides several ser While titles can use all of these services in combination, they can be used independently as well, and this is quite common. For example titles might use PlayFab matchmaking but allocate servers from an alternative multiplayer server hosting solution. Or games might use PlayFab multiplayer servers for hosting, but use their own matchmaking system to bring players together. -Increasingly games are building *cross-network* experiences with players engaging each other from different identity domains (e.g. Xbox Live players interacting with Steam players interacting with custom identity systems). PlayFab's services were designed to support cross-progression and cross-network play. +Increasingly games are building *cross-network* experiences with players engaging each other from different identity domains (for example, Xbox Live players interacting with Steam players interacting with custom identity systems). PlayFab's services were designed to support cross-progression and cross-network play. ## Example multiplayer scenarios @@ -45,7 +45,7 @@ Players often want to control who they play with, preferentially selecting frien Players can also be members of multiple Lobbies at the same time. This allows you to create flexible player groupings such as allowing three friends to remain grouped as they matchmake with others over several matches. -With built-in [real-time notifications](lobby/lobby-and-matchmaking-real-time-notifications.md), members of a Lobby can receive real-time messages when changes occur such as members joining or leaving, or data being written to the Lobby. The same real-time notification mechanism can be used for cross-platform invites, allowing players to listen for an invite whether or not they are a member of a Lobby. Platforms may provide built-in invitation and presence systems that launch toasts and have other beneficial experiences (join in progress from the player profile card) that you should consider integrating if applicable. +With built-in [real-time messages](lobby/lobby-and-matchmaking-real-time-messages.md), members of a Lobby can receive real-time messages when changes occur such as members joining or leaving, or data being written to the Lobby. The same real-time message mechanism can be used for cross-platform invites, allowing players to listen for an invite whether or not they are a member of a Lobby. Platforms may provide built-in invitation and presence systems that launch toasts and have other beneficial experiences (join in progress from the player profile card) that you should consider integrating if applicable. While you can use Lobby for signaling and other limited data-sharing, PlayFab Party is best suited for real-time data transfer and chat. PlayFab Lobby can be used to share PlayFab Party network descriptors or PlayFab multiplayer server session details to the group's data storage. This sharing of session information can allow players to join a friend's session unsolicited. If you are using non-PlayFab services for real-time networking or game hosting, those systems typically have identifying information that you can similarly signal between players using Lobby. @@ -72,11 +72,11 @@ Party utilizes Azure Cognitive Services to transcribe player voice chat and synt ### Game hosting -Real-time multiplayer games typically select a specific player device to host game state (aka "peer to peer") or use a dedicated multiplayer server. If hosting a game on a player device, PlayFab Party is an ideal low-latency device-to-device networking system to synchronize this game state across the session's participants. +Real-time multiplayer games typically select a specific player device to host game state (also known as "peer to peer") or use a dedicated multiplayer server. If hosting a game on a player device, PlayFab Party is an ideal low-latency device-to-device networking system to synchronize this game state across the session's participants. It is difficult to scale peer to peer games when the device count grows. While PlayFab Party provides network encryption and uses relays to protect player IP addresses, having a device operate as host still opens avenues for cheating. -PlayFab Multiplayer Servers provides simple and efficient scaling of multiplayer across Azure's global cloud. Using a small server, for example loading 10 sessions of 10 players each on a F2v2 Linux virtual machine, can efficiently and dramatically simplify your multiplayer design and improve it's reliability compared to a P2P implementation. Sophisticated multiplayer computation can be achieved by setting a server's build configuration to allocate more Azure resources to a session, perhaps using 8 or more cores for a 200 player experience. +PlayFab Multiplayer Servers provides simple and efficient scaling of multiplayer across Azure's global cloud. Using a small server, for example loading 10 sessions of 10 players each on a F2v2 Linux virtual machine, can efficiently and dramatically simplify your multiplayer design and improve its reliability compared to a P2P implementation. Sophisticated multiplayer computation can be achieved by setting a server's build configuration to allocate more Azure resources to a session, perhaps using 8 or more cores for a 200 player experience. - [Learn more about Party](./networking/index.md) - [Learn more about Multiplayer Servers](./servers/index.md) diff --git a/playfab-docs/multiplayer/networking/quickstart.md b/playfab-docs/multiplayer/networking/quickstart.md index 6fceaf2fc..b9c65034f 100644 --- a/playfab-docs/multiplayer/networking/quickstart.md +++ b/playfab-docs/multiplayer/networking/quickstart.md @@ -293,7 +293,7 @@ At this point, you have a party network descriptor and are ready to share it wit ### Use PlayFab Lobby to share the Party network descriptor PlayFab Lobby can be used to temporarily group players as they move into and out of matches and can be used to synchronize the network descriptor so that players can join the same network. -PlayFab Lobby is highly customizable to support a wide variety of gameplay needs on all supported platforms and across platforms. Refer to the [Multiplayer SDK Quickstart](../lobby/lobby-getting-started.md) for more detail about using PlayFab Lobby with real-time notifications. +PlayFab Lobby is highly customizable to support a wide variety of gameplay needs on all supported platforms and across platforms. Refer to the [Multiplayer SDK Quickstart](../lobby/lobby-getting-started.md) for more detail about using PlayFab Lobby with real-time messages. For details about using PlayFab Lobby together with PlayFab Party, refer to [Create a lobby with PlayFab Multiplayer SDK](party-lobby-integration.md). diff --git a/playfab-docs/multiplayer/real-time-notifications/client-methods/receive-message.md b/playfab-docs/multiplayer/real-time-messages/client-methods/receive-message.md similarity index 55% rename from playfab-docs/multiplayer/real-time-notifications/client-methods/receive-message.md rename to playfab-docs/multiplayer/real-time-messages/client-methods/receive-message.md index 27418133e..738f6a191 100644 --- a/playfab-docs/multiplayer/real-time-notifications/client-methods/receive-message.md +++ b/playfab-docs/multiplayer/real-time-messages/client-methods/receive-message.md @@ -11,15 +11,13 @@ ms.date: 03/10/2022 # ReceiveMessage > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. - -Receives messages from [real-time notifications +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. + +Receives messages from [real-time messages subscriptions](../subscribing-to-resources.md). ```text @@ -40,5 +38,5 @@ ReceiveMessage(Message message) - Type [Message](../types/message.md) - Client method [ReceiveSubscriptionChangeMessage](receive-subscription-change-message.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/client-methods/receive-subscription-change-message.md b/playfab-docs/multiplayer/real-time-messages/client-methods/receive-subscription-change-message.md similarity index 53% rename from playfab-docs/multiplayer/real-time-notifications/client-methods/receive-subscription-change-message.md rename to playfab-docs/multiplayer/real-time-messages/client-methods/receive-subscription-change-message.md index eb6964268..46ccc3282 100644 --- a/playfab-docs/multiplayer/real-time-notifications/client-methods/receive-subscription-change-message.md +++ b/playfab-docs/multiplayer/real-time-messages/client-methods/receive-subscription-change-message.md @@ -11,23 +11,21 @@ ms.date: 03/10/2022 # ReceiveSubscriptionChangeMessage > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. Receives [SubscriptionChangeMessages](../types/subscription-change-message.md), -so the client will know when its [subscription](../subscribing-to-resources.md) +so the client knows when its [subscription](../subscribing-to-resources.md) status changes. This message indicates that a request to subscribe or -unsubscribe has finished processing. It is possible that the service will fail -to perform a subscription update in a way where the client will never receive -this message. Because of this, clients should implement a timer so they can -retry the subscription call if no -[SubscriptionChangeMessage](../types/subscription-change-message.md) is received -by this method after 5 seconds. This timer-based retry can be performed a few +unsubscribe finished processing. It's possible that the service fails +to perform a subscription update in a way where the client never receives +this message. For this reason, clients should implement a timer so they can +retry the subscription call if this method doesn't receive a +[SubscriptionChangeMessage](../types/subscription-change-message.md) +after 5 seconds. This timer-based retry can be performed a few times with exponential backoff for subsequent attempts. ```text @@ -47,5 +45,5 @@ ReceiveSubscriptionChangeMessage(SubscriptionChangeMessage subscriptionChangeMes - Type [SubscriptionChangeMessage](../types/subscription-change-message.md) - Client method [ReceiveMessage](receive-message.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-messages/overview.md b/playfab-docs/multiplayer/real-time-messages/overview.md new file mode 100644 index 000000000..482bf71df --- /dev/null +++ b/playfab-docs/multiplayer/real-time-messages/overview.md @@ -0,0 +1,39 @@ +--- +author: WarrenAlpert +title: Real-time messages for Lobby and Matchmaking APIs +description: Real-time messages for Lobby and Matchmaking APIs +ms.author: waralp +ms.topic: reference +ms.service: azure-playfab +ms.date: 03/10/2022 +--- + +# Real-time messages for Lobby and Matchmaking APIs + +> [!NOTE] +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. + +The [Lobby and Matchmaking +services](../lobby/lobby-and-matchmaking.md) offer a real-time +messages feature, which enables individual game clients to subscribe to +receive messages from these services. Game clients subscribe for +messages over a persistent [SignalR WebSocket +connection](/aspnet/core/signalr/introduction). To learn more about +the scenario as a whole, see the [conceptual documentation for Lobby and +Matchmaking real-time +messages](../lobby/lobby-and-matchmaking-real-time-messages.md). + +To use this feature, game clients will first need to [implement a SignalR client +that connects to the SignalR Hub](signalr-hub.md) for real-time messages. +Once connected, the clients can [subscribe to +resources](subscribing-to-resources.md) they would like to receive messages +for. + +## See also + +- [Real-time messages SignalR Hub](signalr-hub.md) +- [Subscribing to resources](subscribing-to-resources.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/server-methods/add-entity-to-session.md b/playfab-docs/multiplayer/real-time-messages/server-methods/add-entity-to-session.md similarity index 64% rename from playfab-docs/multiplayer/real-time-notifications/server-methods/add-entity-to-session.md rename to playfab-docs/multiplayer/real-time-messages/server-methods/add-entity-to-session.md index b95b5aa11..de9473100 100644 --- a/playfab-docs/multiplayer/real-time-notifications/server-methods/add-entity-to-session.md +++ b/playfab-docs/multiplayer/real-time-messages/server-methods/add-entity-to-session.md @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # AddEntityToSession > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. For scenarios where multiple entities are signed in to the same device. Add an additional entity to the session, other than the entity that started the @@ -44,5 +42,5 @@ SharedSessionResponse AddEntityToSession(SharedSessionRequest request) ## See also - Server method [RemoveEntityFromSession](remove-entity-from-session.md). -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/server-methods/end-session.md b/playfab-docs/multiplayer/real-time-messages/server-methods/end-session.md similarity index 56% rename from playfab-docs/multiplayer/real-time-notifications/server-methods/end-session.md rename to playfab-docs/multiplayer/real-time-messages/server-methods/end-session.md index 3ac55a3af..3ca07251d 100644 --- a/playfab-docs/multiplayer/real-time-notifications/server-methods/end-session.md +++ b/playfab-docs/multiplayer/real-time-messages/server-methods/end-session.md @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # EndSession > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. End the session. @@ -41,5 +39,5 @@ EndSessionResponse EndSession(EndSessionRequest request) ## See also - Server method [StartOrRecoverSession](start-or-recover-session.md). -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/server-methods/remove-entity-from-session.md b/playfab-docs/multiplayer/real-time-messages/server-methods/remove-entity-from-session.md similarity index 61% rename from playfab-docs/multiplayer/real-time-notifications/server-methods/remove-entity-from-session.md rename to playfab-docs/multiplayer/real-time-messages/server-methods/remove-entity-from-session.md index de7d93133..c9194ec74 100644 --- a/playfab-docs/multiplayer/real-time-notifications/server-methods/remove-entity-from-session.md +++ b/playfab-docs/multiplayer/real-time-messages/server-methods/remove-entity-from-session.md @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # RemoveEntityFromSession > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. Remove an additional entity that was added to the session with [AddEntityToSession](add-entity-to-session.md). @@ -42,5 +40,5 @@ SharedSessionResponse RemoveEntityFromSession(SharedSessionRequest request) ## See also - Server method [AddEntityToSession](add-entity-to-session.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/server-methods/start-or-recover-session.md b/playfab-docs/multiplayer/real-time-messages/server-methods/start-or-recover-session.md similarity index 64% rename from playfab-docs/multiplayer/real-time-notifications/server-methods/start-or-recover-session.md rename to playfab-docs/multiplayer/real-time-messages/server-methods/start-or-recover-session.md index 3cd904dd3..368dc03c2 100644 --- a/playfab-docs/multiplayer/real-time-notifications/server-methods/start-or-recover-session.md +++ b/playfab-docs/multiplayer/real-time-messages/server-methods/start-or-recover-session.md @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # StartOrRecoverSession > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. Starts a session. @@ -45,5 +43,5 @@ StartOrRecoverSessionResponse StartOrRecoverSession(StartOrRecoverSessionRequest ## See also - Server method [EndSession](end-session.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/signalr-hub.md b/playfab-docs/multiplayer/real-time-messages/signalr-hub.md similarity index 73% rename from playfab-docs/multiplayer/real-time-notifications/signalr-hub.md rename to playfab-docs/multiplayer/real-time-messages/signalr-hub.md index 693dd6bc0..a252a0307 100644 --- a/playfab-docs/multiplayer/real-time-notifications/signalr-hub.md +++ b/playfab-docs/multiplayer/real-time-messages/signalr-hub.md @@ -1,25 +1,23 @@ --- author: WarrenAlpert -title: Real-time notifications SignalR Hub -description: Real-time notifications SignalR Hub +title: Real-time messages SignalR Hub +description: Real-time messages SignalR Hub ms.author: waralp ms.topic: reference ms.service: azure-playfab ms.date: 03/10/2022 --- -# Real-time notifications SignalR Hub +# Real-time messages SignalR Hub > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. - -The real-time notifications feature for [Lobby and Matchmaking +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. + +The real-time messages feature for [Lobby and Matchmaking services](../lobby/lobby-and-matchmaking.md) works through a [SignalR service](/aspnet/core/signalr), which exposes a [SignalR Hub](/aspnet/core/signalr/introduction#hubs). This @@ -28,7 +26,7 @@ they subscribed to](subscribing-to-resources.md). ## Connecting to the SignalR Hub -The first step in receiving real-time notifications is to create a [SignalR +The first step in receiving real-time messages is to create a [SignalR client](/aspnet/core/signalr/client-features). The client can create a connection to the SignalR Hub by [instantiating a HubConnection](/aspnet/core/signalr/dotnet-client#connect-to-a-hub) @@ -43,9 +41,25 @@ documentation](https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/s > when connecting to the SignalR Hub is strongly recommended, and will be > enforced as the only supported encoding in the future. +> [!IMPORTANT] +> The client **must** set `KeepAliveInterval` to **5 seconds** when building the +> `HubConnection`. The backend service will time out and close connections that +> do not receive a keep-alive ping within **10 seconds**. The default SignalR +> `KeepAliveInterval` of 15 seconds is too slow and will cause disconnections. +> +> ```csharp +> var connection = new HubConnectionBuilder() +> .WithUrl(hubUrl, options => { /* auth headers */ }) +> .WithKeepAliveInterval(TimeSpan.FromSeconds(5)) +> .Build(); +> ``` +> +> For more details on SignalR client configuration, see the +> [SignalR configuration documentation](/aspnet/core/signalr/configuration#configure-client-options). + > [!NOTE] > 1. SignalR client implementations expect the URL to omit the `/negotiate` -> portion of this path (ex: HubConnection should created to a URL that ends +> portion of this path (for example, HubConnection should be created to a URL that ends > in `...playfabapi.com/pubsub`). > 1. The auth headers required to call this API can be passed to the SignalR > client via `HttpConnectionOptions` as [seen on this @@ -81,7 +95,7 @@ resources](subscribing-to-resources.md) and receiving messages. | Name | Description | | --- | --- | -| [ReceiveMessage](client-methods/receive-message.md) | Receive a notification message. | +| [ReceiveMessage](client-methods/receive-message.md) | Receive a message. | | [ReceiveSubscriptionChangeMessage](client-methods/receive-subscription-change-message.md) | Receive a SubscriptionChangeMessage to track current subscriptions. | ### Server methods @@ -102,4 +116,4 @@ resources](subscribing-to-resources.md) and receiving messages. ## See also - [Subscribing to resources](subscribing-to-resources.md) -- [Real-time notifications for Lobby and Matchmaking APIs](overview.md) +- [Real-time messages for Lobby and Matchmaking APIs](overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/subscribing-to-resources.md b/playfab-docs/multiplayer/real-time-messages/subscribing-to-resources.md similarity index 65% rename from playfab-docs/multiplayer/real-time-notifications/subscribing-to-resources.md rename to playfab-docs/multiplayer/real-time-messages/subscribing-to-resources.md index 835fda1ad..a7706e1cd 100644 --- a/playfab-docs/multiplayer/real-time-notifications/subscribing-to-resources.md +++ b/playfab-docs/multiplayer/real-time-messages/subscribing-to-resources.md @@ -1,7 +1,7 @@ --- author: WarrenAlpert -title: Subscribing to resources for real-time notifications -description: Subscribing to resources for real-time notifications +title: Subscribing to resources for real-time messages +description: Subscribing to resources for real-time messages ms.author: waralp ms.topic: reference ms.service: azure-playfab @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # Subscribing to resources > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. After the client [connects to the SignalR Hub](signalr-hub.md#connecting-to-the-signalr-hub), and calls @@ -28,7 +26,7 @@ provide the `Connection Handle` that they received when starting the session. For more information about starting and managing a session, see the [SignalR Hub](signalr-hub.md) overview. -To manage resource subscriptions with the services that publish notifications, +To manage resource subscriptions with the services that publish messages, see: | Service | Subscription API | Unsubscription API | @@ -38,5 +36,5 @@ see: ## See also -- [Real-time notifications SignalR Hub](signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](overview.md) +- [Real-time messages SignalR Hub](signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/toc.yml b/playfab-docs/multiplayer/real-time-messages/toc.yml similarity index 100% rename from playfab-docs/multiplayer/real-time-notifications/toc.yml rename to playfab-docs/multiplayer/real-time-messages/toc.yml diff --git a/playfab-docs/multiplayer/real-time-messages/types/end-session-request.md b/playfab-docs/multiplayer/real-time-messages/types/end-session-request.md new file mode 100644 index 000000000..2586213be --- /dev/null +++ b/playfab-docs/multiplayer/real-time-messages/types/end-session-request.md @@ -0,0 +1,40 @@ +--- +author: WarrenAlpert +title: EndSessionRequest real-time messages type +description: EndSessionRequest real-time messages type +ms.author: waralp +ms.topic: reference +ms.service: azure-playfab +ms.date: 03/10/2022 +--- + +# EndSessionRequest + +> [!NOTE] +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. + +```json +{ + "traceParent": "00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01" +} +``` + +## Members + +**`traceParent`**   string + +A valid [W3C TraceContext TraceParent +Header](https://www.w3.org/TR/trace-context/#traceparent-header). + +Example: `00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01` + +## See also + +- Type [EndSessionResponse](end-session-response.md) +- Server method [EndSession](../server-methods/end-session.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/types/end-session-response.md b/playfab-docs/multiplayer/real-time-messages/types/end-session-response.md similarity index 54% rename from playfab-docs/multiplayer/real-time-notifications/types/end-session-response.md rename to playfab-docs/multiplayer/real-time-messages/types/end-session-response.md index 757eee824..240482430 100644 --- a/playfab-docs/multiplayer/real-time-notifications/types/end-session-response.md +++ b/playfab-docs/multiplayer/real-time-messages/types/end-session-response.md @@ -1,7 +1,7 @@ --- author: WarrenAlpert -title: EndSessionResponse real-time notifications type -description: EndSessionResponse real-time notifications type +title: EndSessionResponse real-time messages type +description: EndSessionResponse real-time messages type ms.author: waralp ms.topic: reference ms.service: azure-playfab @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # EndSessionResponse > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. ```json { @@ -47,5 +45,5 @@ Example: `4bf92f3577b34da6a3ce929d0e0e4736` - Type [EndSessionRequest](end-session-request.md) - Server method [EndSession](../server-methods/end-session.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/types/message.md b/playfab-docs/multiplayer/real-time-messages/types/message.md similarity index 73% rename from playfab-docs/multiplayer/real-time-notifications/types/message.md rename to playfab-docs/multiplayer/real-time-messages/types/message.md index ffd49bba3..ade62d771 100644 --- a/playfab-docs/multiplayer/real-time-notifications/types/message.md +++ b/playfab-docs/multiplayer/real-time-messages/types/message.md @@ -1,7 +1,7 @@ --- author: WarrenAlpert -title: Message real-time notifications type -description: Message real-time notifications type +title: Message real-time messages type +description: Message real-time messages type ms.author: waralp ms.topic: reference ms.service: azure-playfab @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # Message > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. ```json { @@ -56,5 +54,5 @@ Example: `4bf92f3577b34da6a3ce929d0e0e4736` ## See also - Client method [ReceiveMessage](../client-methods/receive-message.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/types/response-status.md b/playfab-docs/multiplayer/real-time-messages/types/response-status.md similarity index 74% rename from playfab-docs/multiplayer/real-time-notifications/types/response-status.md rename to playfab-docs/multiplayer/real-time-messages/types/response-status.md index 542ea9266..d1bb66fe0 100644 --- a/playfab-docs/multiplayer/real-time-notifications/types/response-status.md +++ b/playfab-docs/multiplayer/real-time-messages/types/response-status.md @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # Response Status > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. Possible values for the **status** member of [SignalR server method](../signalr-hub.md#server-methods) responses. @@ -39,5 +37,5 @@ method](../signalr-hub.md#server-methods) responses. - Type [EndSessionResponse](end-session-response.md) - Type [SharedSessionResponse](shared-session-response.md) - Type [StartOrRecoverSessionResponse](start-or-recover-session-response.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/types/shared-session-request.md b/playfab-docs/multiplayer/real-time-messages/types/shared-session-request.md similarity index 65% rename from playfab-docs/multiplayer/real-time-notifications/types/shared-session-request.md rename to playfab-docs/multiplayer/real-time-messages/types/shared-session-request.md index fb3009018..750a13069 100644 --- a/playfab-docs/multiplayer/real-time-notifications/types/shared-session-request.md +++ b/playfab-docs/multiplayer/real-time-messages/types/shared-session-request.md @@ -1,7 +1,7 @@ --- author: WarrenAlpert -title: SharedSessionRequest real-time notifications type -description: SharedSessionRequest real-time notifications type +title: SharedSessionRequest real-time messages type +description: SharedSessionRequest real-time messages type ms.author: waralp ms.topic: reference ms.service: azure-playfab @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # SharedSessionRequest > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. ```json { @@ -58,5 +56,5 @@ Example: `00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01` - Server method [AddEntityToSession](../server-methods/add-entity-to-session.md) - Server method [RemoveEntityFromSession](../server-methods/remove-entity-from-session.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/types/shared-session-response.md b/playfab-docs/multiplayer/real-time-messages/types/shared-session-response.md similarity index 61% rename from playfab-docs/multiplayer/real-time-notifications/types/shared-session-response.md rename to playfab-docs/multiplayer/real-time-messages/types/shared-session-response.md index 6d379f8d3..207431d4f 100644 --- a/playfab-docs/multiplayer/real-time-notifications/types/shared-session-response.md +++ b/playfab-docs/multiplayer/real-time-messages/types/shared-session-response.md @@ -1,7 +1,7 @@ --- author: WarrenAlpert -title: SharedSessionResponse real-time notifications type -description: SharedSessionResponse real-time notifications type +title: SharedSessionResponse real-time messages type +description: SharedSessionResponse real-time messages type ms.author: waralp ms.topic: reference ms.service: azure-playfab @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # SharedSessionResponse > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. ```json { @@ -56,5 +54,5 @@ Example: `4bf92f3577b34da6a3ce929d0e0e4736` - Server method [AddEntityToSession](../server-methods/add-entity-to-session.md) - Server method [RemoveEntityFromSession](../server-methods/remove-entity-from-session.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/types/start-or-recover-session-request.md b/playfab-docs/multiplayer/real-time-messages/types/start-or-recover-session-request.md similarity index 61% rename from playfab-docs/multiplayer/real-time-notifications/types/start-or-recover-session-request.md rename to playfab-docs/multiplayer/real-time-messages/types/start-or-recover-session-request.md index a5a050ce0..081b30e46 100644 --- a/playfab-docs/multiplayer/real-time-notifications/types/start-or-recover-session-request.md +++ b/playfab-docs/multiplayer/real-time-messages/types/start-or-recover-session-request.md @@ -1,7 +1,7 @@ --- author: WarrenAlpert -title: StartOrRecoverSessionRequest real-time notifications type -description: StartOrRecoverSessionRequest real-time notifications type +title: StartOrRecoverSessionRequest real-time messages type +description: StartOrRecoverSessionRequest real-time messages type ms.author: waralp ms.topic: reference ms.service: azure-playfab @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # StartOrRecoverSessionRequest > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. ```json { @@ -48,5 +46,5 @@ Example: `00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01` - Type [StartOrRecoverSessionResponse](start-or-recover-session-response.md) - Server method [StartOrRecoverSession](../server-methods/start-or-recover-session.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/types/start-or-recover-session-response.md b/playfab-docs/multiplayer/real-time-messages/types/start-or-recover-session-response.md similarity index 73% rename from playfab-docs/multiplayer/real-time-notifications/types/start-or-recover-session-response.md rename to playfab-docs/multiplayer/real-time-messages/types/start-or-recover-session-response.md index 02594bbb3..bd9f91996 100644 --- a/playfab-docs/multiplayer/real-time-notifications/types/start-or-recover-session-response.md +++ b/playfab-docs/multiplayer/real-time-messages/types/start-or-recover-session-response.md @@ -1,7 +1,7 @@ --- author: WarrenAlpert -title: StartOrRecoverSessionResponse real-time notifications type -description: StartOrRecoverSessionResponse real-time notifications type +title: StartOrRecoverSessionResponse real-time messages type +description: StartOrRecoverSessionResponse real-time messages type ms.author: waralp ms.topic: reference ms.service: azure-playfab @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # StartOrRecoverSessionResponse > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. ```json { @@ -51,7 +49,7 @@ A list of topic strings, matching the topic strings returned when [subscribing to resources](../subscribing-to-resources.md). This list only contains values if a session was recovered from an old `Connection Handle` and subscriptions were found to recover. It's possible that some subscriptions that are expected here -will not be recovered. If there are any missing subscriptions the client should +will not be recovered. If there are any missing subscriptions, the client should resubscribe to those resources. Example: `["Opaque~Topic~String~6183258", "Another~Opaque~Topic~String~843156"]` @@ -75,5 +73,5 @@ Example: `4bf92f3577b34da6a3ce929d0e0e4736` - Type [StartOrRecoverSessionRequest](start-or-recover-session-request.md) - Server method [StartOrRecoverSession](../server-methods/start-or-recover-session.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/types/subscription-change-message.md b/playfab-docs/multiplayer/real-time-messages/types/subscription-change-message.md similarity index 80% rename from playfab-docs/multiplayer/real-time-notifications/types/subscription-change-message.md rename to playfab-docs/multiplayer/real-time-messages/types/subscription-change-message.md index 03df9b300..dee4dad28 100644 --- a/playfab-docs/multiplayer/real-time-notifications/types/subscription-change-message.md +++ b/playfab-docs/multiplayer/real-time-messages/types/subscription-change-message.md @@ -1,7 +1,7 @@ --- author: WarrenAlpert -title: SubscriptionChangeMessage real-time notifications type -description: SubscriptionChangeMessage real-time notifications type +title: SubscriptionChangeMessage real-time messages type +description: SubscriptionChangeMessage real-time messages type ms.author: waralp ms.topic: reference ms.service: azure-playfab @@ -11,13 +11,11 @@ ms.date: 03/10/2022 # SubscriptionChangeMessage > [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. +> The REST and SignalR APIs documented here are more complex than the client +> SDKs. Consider using the +> [Lobby C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) +> or [Matchmaking C++ SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md) +> instead, unless those SDKs don't meet your needs. ```json { @@ -92,5 +90,5 @@ Example: `4bf92f3577b34da6a3ce929d0e0e4736` - Client method [ReceiveSubscriptionChangeMessage](../client-methods/receive-subscription-change-message.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) +- [Real-time messages SignalR Hub](../signalr-hub.md) +- [Real-time messages for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/overview.md b/playfab-docs/multiplayer/real-time-notifications/overview.md deleted file mode 100644 index a29e0c945..000000000 --- a/playfab-docs/multiplayer/real-time-notifications/overview.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -author: WarrenAlpert -title: Real-time notifications for Lobby and Matchmaking APIs -description: Real-time notifications for Lobby and Matchmaking APIs -ms.author: waralp -ms.topic: reference -ms.service: azure-playfab -ms.date: 03/10/2022 ---- - -# Real-time notifications for Lobby and Matchmaking APIs - -> [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. - -The [Lobby and Matchmaking -services](../lobby/lobby-and-matchmaking.md) offer a real-time -notifications feature, which enables individual game clients to subscribe to -receive notifications from these services. Game clients subscribe for -notifications over a persistent [SignalR WebSocket -connection](/aspnet/core/signalr/introduction). To learn more about -the scenario as a whole, see the [conceptual documentation for Lobby and -Matchmaking real-time -notifications](../lobby/lobby-and-matchmaking-real-time-notifications.md). - -To use this feature, game clients will first need to [implement a SignalR client -that connects to the SignalR Hub](signalr-hub.md) for real-time notifications. -Once connected, the clients can [subscribe to -resources](subscribing-to-resources.md) they would like to receive notifications -for. - -## See also - -- [Real-time notifications SignalR Hub](signalr-hub.md) -- [Subscribing to resources](subscribing-to-resources.md) diff --git a/playfab-docs/multiplayer/real-time-notifications/types/end-session-request.md b/playfab-docs/multiplayer/real-time-notifications/types/end-session-request.md deleted file mode 100644 index d1b272d74..000000000 --- a/playfab-docs/multiplayer/real-time-notifications/types/end-session-request.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -author: WarrenAlpert -title: EndSessionRequest real-time notifications type -description: EndSessionRequest real-time notifications type -ms.author: waralp -ms.topic: reference -ms.service: azure-playfab -ms.date: 03/10/2022 ---- - -# EndSessionRequest - -> [!NOTE] -> Using Lobby, Matchmaking, and real-time notifications directly with REST and -> SignalR APIs is significantly more complex than using client SDKs such as the -> [Lobby C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pflobby/pflobby_members.md) -> and [Matchmaking C++ -> SDK](../../lobby/playfabmultiplayerreference-cpp/pfmatchmaking/pfmatchmaking_members.md), -> and should only be done if the SDKs don't meet your needs. - -```json -{ - "traceParent": "00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01" -} -``` - -## Members - -**`traceParent`**   string - -A valid [W3C TraceContext TraceParent -Header](https://www.w3.org/TR/trace-context/#traceparent-header). - -Example: `00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01` - -## See also - -- Type [EndSessionResponse](end-session-response.md) -- Server method [EndSession](../server-methods/end-session.md) -- [Real-time notifications SignalR Hub](../signalr-hub.md) -- [Real-time notifications for Lobby and Matchmaking APIs](../overview.md) diff --git a/playfab-docs/player-progression/game-saves/linking.md b/playfab-docs/player-progression/game-saves/linking.md new file mode 100644 index 000000000..e9e35ef25 --- /dev/null +++ b/playfab-docs/player-progression/game-saves/linking.md @@ -0,0 +1,395 @@ +--- +title: Account linking strategies for PlayFab Game Saves +author: amccalib +description: Requirements and strategies for linking player accounts across platforms when using PlayFab Game Saves. +ms.author: andmcc +ms.date: 12/05/2025 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, game saves, account linking, cross-progression, identity linking +ms.localizationpriority: medium +--- + +# Account linking strategies for PlayFab Game Saves + +## Primary linking identity + +The first requirement for any cross-progression strategy is to determine which player identity will span across gaming platforms. The player needs to be able to sign in with this identity on any device on which the game is available. For a first-party title, this is often the Microsoft account (MSA)/Xbox account. For many third parties, this is likely a publisher identity exposed through an OpenID Connect implementation. The two requirements for this player identity are: + +1. Available to players on every platform on which they could play the game +2. Supported by an existing PlayFab Login call, such as `LoginWithXbox` or `LoginWithOpenIdConnect` + +Beyond those two requirements, it's useful if the identity supports some sort of device-based caching and silent sign-in on subsequent game launches. This isn't a hard requirement but can reduce workflow complexity and/or player friction. + +## Platform-native identity + +A platform-native identity is the account system provided by the platform on which the player is running the game. Examples include: +- Steam: Steam account and auth ticket (`ISteamUser::GetAuthTicketForWebApi`) +- Xbox on PC/Console: MSA/Xbox `XUserHandle` and XSTS token +- PlayStation: PSN Online ID / account +- Nintendo: Nintendo Service Account / device ID + +These identities are typically used to create and reuse a `PFLocalUserHandle` for the active player on a given device (for example, `PFLocalUserCreateHandleWithSteamUser` or wrapping an `XUserHandle`). They can also be used to authenticate via provider-specific PlayFab Login APIs (for example, `LoginWithSteam`, `LoginWithXbox`) when appropriate. + +In cross-progression scenarios, platform-native identities are linked to the primary linking identity, so that progress and entitlements follow the player across platforms. The recommended workflows in this document use the platform-native identity as the local user context and the primary linking identity as the cross-platform anchor. + +## Linking strategy options + +This document explores two related strategies: + +1. All players are **required** to link their platform-native identity with your primary linking identity before playing. +2. Linking between the platform-native and primary linking identities is **optional** but heavily encouraged before playing. + +The first strategy is easier to implement and avoids difficult decisions for players involving potential lost progress down the road. It does increase initial friction getting started with the game and can lead to negative sentiment in cases where players don't see sufficient value in the upfront linking requirement. It's especially unsuitable for many free-to-play and mobile games that depend on extremely low barriers to bring in as many players as possible. + +The second strategy improves the up-front player experience in exchange for potential conflicts and hard decisions in the future, in addition to increased coding complexity for developers. Players can get started without any additional sign-in requirements. They can even start completely offline if the game supports it. That flexibility can create a problem down the road when they do decide to link. It's possible that the identity they link to may have preexisting progress on another platform. If that's the case, establishing the link could involve either abandoned progress or a messy merge the game will need to handle. Even if games do choose this strategy, they're encouraged to promote linking as early as possible, describe the benefits of linking, and warn of the potential risks of not linking. + +Ultimately, the choice between these strategies must be driven from a business perspective. One isn't clearly superior to the other. There's clear market evidence that transitioning from option 2 to option 1 after launch creates player dissatisfaction. This indicates the importance of getting this choice right early and designing around it from the start. + +## Desired state + +Regardless of strategy, the ultimate goal is to get every player into the same state. Their primary linking identity should be linked with the platform-native identity on every device on which they play. In that state, progress is consistently tied to the primary linking identity and platform-native identities can also be used as an effective proxy identity for the primary identity on all platforms. + +On some platforms, it's possible that the primary linking identity **is** the platform-native identity (first-party games running on an Xbox). In those cases, it becomes trivial to attain the desired state. This document doesn't explore those in any depth, as existing sign-in and linking guidance is adequate. + +## LocalUser versus login + +It's important to differentiate between two related but separate concepts that exist within the PlayFab SDK. + +A LocalUserCreate call constructs a local user object and returns a PFLocalUserHandle without performing any authentication. It identifies and caches the user by a platform-specific or persisted local ID (for example, wrapping an XUserHandle) so you can reuse the same local context across operations and game instances. This operation is purely local: it doesn't make network requests, obtain an entity token, or create a PlayFab account. + +In contrast, a Login call authenticates the local user with PlayFab and establishes an authenticated entity, including tokens and IDs. The Login call performs network requests (such as /Client/LoginWithXbox) and respects flags like createAccount, and once successful, the result is cached so subsequent calls can reuse the authenticated state. + +In short, creating a local user sets up local identity and handle management required for PlayFab Game Saves, while signing in is the step that contacts PlayFab to authenticate and enable APIs that require an entity. + +## Strategy 1 - required primary identity linking + +For the purposes of illustrating this strategy, we're going to discuss an Xbox first-party game shipping on Steam. The game uses Xbox/MSA as its primary linking identity. It requires all players to sign in to their Xbox/MSA prior to any gameplay. It still uses a LocalUserHandle based on the Steam identity, but blocks actual sign-in until the player has created and linked an Xbox identity. On subsequent launches, it can go straight through using the Steam identity, as it's been verified as linked. + +### High-level summary + +- Player must sign in with the cross-platform identity (Xbox/MSA) before playing. +- Create a local player from the platform account (Steam) but hold online play until Xbox/MSA sign-in is complete. +- After Xbox/MSA sign-in, link the platform account to the cross-platform account. +- Refresh the local platform profile so it's connected to the cross-platform account. +- Future launches are seamless: the player can go straight to play because the link is established. + +### Detailed walkthrough + +**Create a Steam local user handle** +- Call `PFLocalUserCreateHandleWithSteamUser(serviceConfigHandle, customContext, outLocalUserHandle)`. +- Result: `PFLocalUserHandle`; no authentication yet. + +**Attempt to go online** +- Call `PFLocalUserLoginAsync(localUserHandle, /*createAccount*/ false, async)`. +- On completion, if `PFLocalUserLoginGetResult` fails with `E_PF_ACCOUNT_NOT_FOUND`, trigger Xbox sign-in to bootstrap the account. +- If `PFLocalUserLoginGetResult` succeeds, we already have an account in the desired state and it's online. Workflow complete. + +> [!NOTE] +> If your title requires the cross-platform identity to remain linked to the current user (for example, the game requires Xbox sign-in and expects the entity's Xbox link to match the currently signed-in Xbox account), a successful platform login alone isn't sufficient. Call `PFAccountManagementClientGetAccountInfoAsync` after login to verify the cross-platform link matches the current user. If it doesn't, the entity may be tied to a stale cross-platform identity—follow the **Sign in via Xbox** and **Link Steam** steps below to realign. + +**Sign in via Xbox** +- Build `PFAuthenticationLoginWithXUserRequest`: + - Set `createAccount=true` to create the PlayFab account if needed. + - Provide the `XUserHandle` from your signed-in Xbox user on the PC. +- Call `PFAuthenticationLoginWithXUserAsync(serviceConfigHandle, request, async)`. +- Complete with `PFAuthenticationLoginWithXUserGetResultSize(...)` and `PFAuthenticationLoginWithXUserGetResult(...)` to obtain `PFEntityHandle`. +- Note: Use `PFAuthenticationLoginWithXbox` if the LoginWithXUser variant isn't available. This requires you to extract the XSTS token from the `XUserHandle` yourself. + +**Link Steam to the authenticated (Xbox-backed) PlayFab account** +- Build a client link request with the current Steam auth ticket (from `ISteamUser::GetAuthTicketForWebApi` or equivalent in your integration; confirm exact function name in your code). +- Call `PFAccountManagementClientLinkSteamAccountAsync(entityHandle, linkRequest, async)`. +- Note: "LinkSteamAccount" is under Account Management, not Authentication. +- After success, the player's Steam identity is linked to the Xbox-backed PlayFab account. + +**Associate Steam local user with an entity (post-link)** +- Call `PFLocalUserLoginAsync(steamLocalUserHandle, /*createAccount*/ false, async)` again. +- `PFLocalUserLoginGetResult` now succeeds; the resulting `PFEntityHandle` is bound to the Steam local user. + +**Normal operation going forward** +- Game Save and other online APIs use the authenticated `PFEntityHandle`. +- Subsequent game launches can go straight to playing because all the linking is in place. + +Notes +- `PFLocalUserCreateHandleWithSteamUser` doesn't sign in on its own but attempting to call `PFGameSaveFilesAddUserWithUiAsync` results in a sign-in attempt. Ensure you've gone through the account linking flow prior to that call. + +### Link-conflict handling + +Two distinct conflicts can arise when linking Steam to the Xbox-backed entity. Each requires a different remedy: + +| Error | Meaning | Remedy | +|---|---|---| +| `E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED` | The current Steam account is linked to a **different** PlayFab entity. | Call `PFAccountManagementClientLinkSteamAccountAsync` again with `forceLink=true` (after consent). This moves the Steam link to the current entity. | +| `E_PF_ACCOUNT_ALREADY_LINKED` | The current entity already has a **different** Steam account linked. | Call `PFAccountManagementClientUnlinkSteamAccountAsync` to remove the old Steam link first, then call `PFAccountManagementClientLinkSteamAccountAsync` for the new Steam account. `forceLink` doesn't resolve this error. | + +**Recommended flow:** + +- After Xbox sign-in, call `PFAccountManagementClientGetAccountInfoAsync(xboxEntity, getInfoRequest, async)` to fetch account info and inspect linked identities. +- If the entity already has a **different Steam account** linked: + - Warn the player that proceeding removes the old Steam association from this entity. Obtain consent. + - Call `PFAccountManagementClientUnlinkSteamAccountAsync(xboxEntity, unlinkRequest, async)` to remove the existing Steam link. + - Then call `PFAccountManagementClientLinkSteamAccountAsync` with the current Steam ticket. +- If the link call returns `E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED` (the Steam account belongs to another entity): + - Warn the player that this Steam account is associated with a different PlayFab account and linking it here removes that association. + - Retry with `forceLink=true` after consent. + +This preserves player agency and avoids unintentionally overriding links while still providing a clear path to reconcile identities. + +### Sample C++ flow (Steam-first gate, Xbox bootstrap, link Steam, sign in with Steam again): + +> [!IMPORTANT] +> This sample uses `static XAsyncBlock` variables to simplify lifetime management. Production code should allocate async blocks dynamically (for example, as part of the context struct) to support concurrent or reentrant calls. + +```cpp +// Assumes: serviceConfigHandle, taskQueue, and a signed-in XUserHandle (xUserHandle) are available +// +// NOTE: RETURN_IF_FAILED is used here for brevity. Because XAsyncBlock callbacks return void, +// production code should replace it with proper error handling (for example, log and return). + +// Single context block used by multiple nested callbacks +struct Strategy1AsyncCtx +{ + PFServiceConfigHandle serviceConfig{}; + XTaskQueueHandle queue{}; + PFLocalUserHandle steamUser{}; + XUserHandle xUserHandle{}; + PFEntityHandle xboxEntity{}; +}; + +// 1) Create Steam local user +PFLocalUserHandle steamUser{}; +RETURN_IF_FAILED(PFLocalUserCreateHandleWithSteamUser(serviceConfigHandle, /*customContext*/ nullptr, &steamUser)); + +// 2) Attempt Steam login with createAccount=false +XAsyncBlock steamLoginAsync{}; +steamLoginAsync.queue = taskQueue; +// Provide context for nested callbacks +// NOTE: Caller is responsible for deleting s1ctx in the terminal callback. +Strategy1AsyncCtx* s1ctx = new Strategy1AsyncCtx{ serviceConfigHandle, taskQueue, steamUser, xUserHandle }; +steamLoginAsync.context = s1ctx; +steamLoginAsync.callback = [](XAsyncBlock* async) +{ + auto* ctx = static_cast(async->context); + // Try to get result-size; failure means login failed + size_t bufferSize{}; + HRESULT hrSize = PFLocalUserLoginGetResultSize(async, &bufferSize); + if (FAILED(hrSize)) + { + if (hrSize == E_PF_ACCOUNT_NOT_FOUND) + { + // 3) Bootstrap via Xbox (provider API), then link Steam + PFAuthenticationLoginWithXUserRequest xreq{}; + xreq.createAccount = true; + xreq.user = ctx->xUserHandle; // supply your signed-in XUserHandle + + static XAsyncBlock xboxLoginAsync{}; // ensure lifetime until callback + xboxLoginAsync.queue = async->queue; + xboxLoginAsync.context = ctx; + xboxLoginAsync.callback = [](XAsyncBlock* xAsync) + { + auto* ctx = static_cast(xAsync->context); + // Obtain Xbox login result + PFEntityHandle xboxEntity{}; + size_t xSize{}; + RETURN_IF_FAILED(PFAuthenticationLoginWithXUserGetResultSize(xAsync, &xSize)); + std::vector xbuf(xSize); + PFAuthenticationLoginResult const* xres{}; + RETURN_IF_FAILED(PFAuthenticationLoginWithXUserGetResult(xAsync, &xboxEntity, xbuf.size(), xbuf.data(), &xres, nullptr)); + ctx->xboxEntity = xboxEntity; + + // Detect existing Steam linkage before linking + // Build a minimal GetAccountInfo request + // Then call PFAccountManagementClientGetAccountInfoAsync(xboxEntity, &getInfoReq, &getInfoAsync) + // and inspect the linked accounts section of the result. + // + // If the entity already has a DIFFERENT Steam account linked: + // Call PFAccountManagementClientUnlinkSteamAccountAsync(xboxEntity, &unlinkReq, &unlinkAsync) + // to remove the old Steam link, then proceed to link the current Steam account below. + // forceLink does NOT resolve this case (E_PF_ACCOUNT_ALREADY_LINKED error). + // + // If a DIFFERENT entity has this Steam account claimed: + // The link call below will fail with E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED. + // Retry with forceLink=true after obtaining player consent. + + // Link Steam to Xbox-backed account + PFAccountManagementClientLinkSteamAccountRequest linkReq{}; + linkReq.steamTicket = GetCurrentSteamTicket(); // your helper wrapping ISteamUser::GetAuthTicketForWebApi + bool isServiceSpecific = true; + linkReq.ticketIsServiceSpecific = &isServiceSpecific; + // To resolve E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED after consent: + // bool forceLink = true; + // linkReq.forceLink = &forceLink; + + static XAsyncBlock linkAsync{}; + linkAsync.queue = xAsync->queue; + linkAsync.context = ctx; + linkAsync.callback = [](XAsyncBlock* linkXAsync) + { + auto* ctx = static_cast(linkXAsync->context); + RETURN_IF_FAILED(XAsyncGetStatus(linkXAsync, false)); + + // 4) Re-login Steam local user to bind entity handle + static XAsyncBlock steamReloginAsync{}; + steamReloginAsync.queue = linkXAsync->queue; + steamReloginAsync.context = ctx; + steamReloginAsync.callback = [](XAsyncBlock* reloginAsync) + { + auto* ctx = static_cast(reloginAsync->context); + PFEntityHandle entity{}; + RETURN_IF_FAILED(PFLocalUserLoginGetResult(reloginAsync, &entity, 0, nullptr, nullptr, nullptr)); + // Now the Steam local user has an associated entity + }; + + RETURN_IF_FAILED(PFLocalUserLoginAsync(ctx->steamUser, /*createAccount*/ false, &steamReloginAsync)); + }; + + RETURN_IF_FAILED(PFAccountManagementClientLinkSteamAccountAsync(ctx->xboxEntity, &linkReq, &linkAsync)); + }; + + // NOTE: On platforms that don't support LoginWithXUser, replace this with PFAuthenticationLoginWithXboxAsync + RETURN_IF_FAILED(PFAuthenticationLoginWithXUserAsync(ctx->serviceConfig, &xreq, &xboxLoginAsync)); + } + // Other failures: handle/log as needed + return; + } + + // Steam login succeeded: get entity + PFEntityHandle entity{}; + RETURN_IF_FAILED(PFLocalUserLoginGetResult(async, &entity, 0, nullptr, nullptr, nullptr)); + // Use entity as needed; PFServices/GameSave APIs, etc. +}; + +RETURN_IF_FAILED(PFLocalUserLoginAsync(steamUser, /*createAccount*/ false, &steamLoginAsync)); +``` + +Implementation notes: +- Use `E_PF_ACCOUNT_NOT_FOUND` to decide the Xbox bootstrap path; handle other errors separately. +- Keep using the Steam `PFLocalUserHandle`; provider-specific Xbox sign-in returns an `entityHandle` used only to link Steam. +- After linking, sign in with Steam again to bind the entity to the LocalUser. +- Ensure you fetch a fresh Steam ticket for linking. +- Close handles when no longer needed (`PFLocalUserCloseHandle`, `PFEntityCloseHandle`). + +## Strategy 2 - optional primary identity linking + +For this scenario, the game runs on Steam and uses Xbox/MSA as the primary linking identity. Players can begin playing without immediately signing in to Xbox/MSA. The game encourages linking early with clear benefits and warnings, but initial gameplay isn't blocked. + +### High-level summary +- Create a local player using the platform account (Steam) and try to play online without creating a new account. +- If online works, continue; if not, offer a choice: + - Sign in with the cross-platform identity (Xbox/MSA) to create a unified account, or + - Create a platform-only account now and start playing immediately. +- Encourage early linking to Xbox/MSA by explaining benefits and risks. +- When the player chooses to link: + - If linking succeeds directly, continue playing with a unified account. + - If the Xbox/MSA account already has progress elsewhere, pause and ask which progress to keep (reconciliation): + - Keep Xbox/MSA progress and attach the current platform account. + - Keep current platform progress and defer linking. +- After linking, refresh the local platform profile so it's connected to the unified account. +- Future launches are seamless: the player can go straight to play (assuming linking wasn't deferred). + +### Detailed walkthrough + +**Create a Steam local user handle** +- Call `PFLocalUserCreateHandleWithSteamUser(serviceConfigHandle, customContext, outLocalUserHandle)`. +- Result: `PFLocalUserHandle`; no authentication yet. + +**Attempt to go online (silent Steam path)** +- Call `PFLocalUserLoginAsync(localUserHandle, /*createAccount*/ false, async)`. +- On completion: + - If `PFLocalUserLoginGetResult` succeeds, use the resulting `PFEntityHandle` and proceed online. + - Check if the Steam-backed account is already linked to Xbox/MSA. Call `PFAccountManagementClientGetAccountInfoAsync(entityHandle, getInfoRequest, async)` and inspect linked identities. If not linked, prompt the player to link Xbox using the flow below (non-blocking), so future cross-progression works seamlessly. + - If `PFLocalUserLoginGetResult` fails with `E_PF_ACCOUNT_NOT_FOUND`, the player remains offline until an account is created. Offer two choices: + - Create an Xbox-backed PlayFab account now: sign in with Xbox/MSA (for example, `PFAuthenticationLoginWithXUserAsync`). + - Sign in with Steam now and start playing: call `PFLocalUserLoginAsync(localUserHandle, /*createAccount*/ true, async)` to create a Steam-backed PlayFab account bound to the local handle; on success, use the resulting `PFEntityHandle` to proceed online immediately. + - For other errors, handle gracefully (retry/backoff). + +**Prompt to link Xbox (non-blocking)** +- Present benefits of linking (cross-progression, entitlement portability). +- Offer Xbox/MSA sign-in. + +**Sign in via Xbox (bootstrap or late-link with reconciliation detection)** +- If the player is initiating Xbox linking later (they already have a Steam-backed `PFEntityHandle` from the current session): + - Don't create a new Xbox-backed account. + - Attempt to link the Xbox identity directly to the current Steam-backed account by calling the appropriate link API (for example, `PFAccountManagementClientLinkXboxAccountAsync(currentSteamEntity, linkRequest, async)`). + - If the link succeeds, the Xbox/MSA identity is now linked; continue normal operation. + - If the link fails with a preexisting link/conflict error (Xbox identity already linked elsewhere), enter Account Reconciliation mode. Immediately perform Xbox/MSA sign-in with `createAccount=false` (for example, `PFAuthenticationLoginWithXUserAsync`) to obtain the Xbox-backed `PFEntityHandle`, then fetch profile metadata for context before prompting the player. After consent, proceed to linking decisions. +- If the player has no existing account for Xbox (bootstrap path): + - First attempt Xbox/MSA sign-in with `createAccount=false` using `PFAuthenticationLoginWithXUserAsync` (or `PFAuthenticationLoginWithXboxAsync` where `LoginWithXUser` isn't available). + - If sign-in succeeds: the Xbox/MSA account already has a PlayFab account and likely existing progress. Enter Account Reconciliation mode to choose which progress to keep. + - If sign-in fails with `E_PF_ACCOUNT_NOT_FOUND`: proceed to create the PlayFab account by signing in again with `createAccount=true`. + - Complete with `PFAuthenticationLoginWithXUserGetResultSize(...)` and `PFAuthenticationLoginWithXUserGetResult(...)` to obtain `PFEntityHandle`. + +**Link Steam to the authenticated (Xbox-backed) PlayFab account** +- Applicable when you just created a fresh Xbox-backed PlayFab account (no existing Steam links). +- If you entered Account Reconciliation earlier, linking decisions and any required `forceLink` actions are handled there; skip this step. +- Build a client link request with the current Steam auth ticket (from `ISteamUser::GetAuthTicketForWebApi` or your integration). +- Call `PFAccountManagementClientLinkSteamAccountAsync(entityHandle, linkRequest, async)` with `forceLink=false` (default). This is expected to succeed for a fresh account. +- If the link fails, treat it as an error condition (unexpected conflict or auth failure). Surface an error to the player and consider prompting them to sign in again before retrying. +- After success, the player's Steam identity is linked to the Xbox-backed PlayFab account. + +**Associate Steam local user with an entity (post-link)** +- Call `PFLocalUserLoginAsync(steamLocalUserHandle, /*createAccount*/ false, async)` again. +- `PFLocalUserLoginGetResult` now succeeds; the resulting `PFEntityHandle` is bound to the Steam local user. + +**Normal operation going forward** +- Game Save and other online APIs use the authenticated `PFEntityHandle`. +- Subsequent game launches will be able to go straight to playing because all the linking is in place. + +Notes +- Don't block initial gameplay with the Xbox/MSA sign-in; prompt early but allow players to defer. +- `PFLocalUserCreateHandleWithSteamUser` doesn't sign in on its own. Ensure linking flows are completed before calling APIs that trigger sign-in like `PFGameSaveFilesAddUserWithUiAsync`. + +### Account reconciliation (existing progress on Xbox/MSA) + +When a player signs in with an Xbox/MSA account that already has progress (for example, from console or another platform), you must avoid blindly creating a new account or overriding existing links. Use a cautious, two-phase approach to detect and reconcile. + +> [!TIP] +> **Player-facing wording:** In developer docs we use "reconciliation." For player UI, prefer clearer terms like "Game Profile Selection", "Choose Progress", or "Keep Existing Progress" to reduce confusion and emphasize that the player is selecting one profile to continue with (not merging). + +#### Detection phase +- Reconciliation can be entered via two paths: + 1) Existing Xbox/MSA account detected: attempt Xbox/MSA sign-in with `createAccount=false`. + - If sign-in succeeds, the Xbox/MSA identity already has a PlayFab account and likely existing progress—enter reconciliation. + - If sign-in fails with `E_PF_ACCOUNT_NOT_FOUND`, proceed with bootstrap (`createAccount=true`). There's no need to enter reconciliation. + 2) Late-link conflict detected: when linking Xbox/MSA to the current Steam-backed account, the link fails with a preexisting-link/conflict error (Xbox identity already linked with a different Steam identity). + - Immediately perform Xbox/MSA sign-in with `createAccount=false` (for example, `PFAuthenticationLoginWithXUserAsync`) to obtain the Xbox-backed `PFEntityHandle`. + - Fetch profile metadata (for example, recent progression, save slots, timestamps) to present context. + - Enter reconciliation to decide which progress to keep. + +#### Reconciliation phase +- Recommend the straightforward option: keep Xbox/MSA (primary linking identity) progress and abandon local Steam progress. This preserves the cross-platform anchor and avoids complex merges. +- Players effectively have three choices (games may choose to only offer 1-2 of these): + 1) Keep Xbox/MSA progress (recommended): proceed to link the current Steam account to the existing Xbox-backed PlayFab account. + 2) Keep current Steam progress and cancel linking: continue with the Steam-backed account for now; don't link or override Xbox/MSA data. Offer linking again next time. + 3) Keep current Steam progress and abandon Xbox progress: switch to the Steam-backed account and intentionally drop Xbox/MSA progress. This path requires explicit game design consideration and shouldn't be attempted lightly, especially if other platform-native identities are already attached to the Xbox account. For this document, we don't cover implementation details for this scenario. +- Prior to committing: + - Call `PFAccountManagementClientGetAccountInfoAsync` for the Xbox entity to inspect existing provider links and verify whether a Steam link already exists. + - If the entity has a **different Steam account** linked, warn the player that this existing Steam association is removed from the entity before the new one can be added. This requires calling `PFAccountManagementClientUnlinkSteamAccountAsync` before linking the current Steam account. `forceLink` doesn't resolve this scenario. + - If the **current Steam account** is linked to a **different entity**, calling `PFAccountManagementClientLinkSteamAccountAsync` returns `E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED`. Warn that linking moves the Steam identity away from the other entity, then retry with `forceLink=true` after consent. + +#### Commit actions (based on player choice) +- Player chooses Xbox/MSA progress: + - Ensure Xbox sign-in entity is obtained (perform `PFAuthenticationLoginWithXUserAsync` with `createAccount=false` if not already done during detection). + - If the Xbox entity already has a different Steam account linked, call `PFAccountManagementClientUnlinkSteamAccountAsync` to remove it first. + - Link current Steam to Xbox-backed account. If the call returns `E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED` (Steam is on another entity), retry with `forceLink=true` after consent. + - Sign in with the Steam local user again (`PFLocalUserLoginAsync(..., /*createAccount*/ false, ...)`) to bind the entity. +- Player chooses Steam progress: + - If no PlayFab account exists for Steam yet, create/bind via `PFLocalUserLoginAsync(..., /*createAccount*/ true, ...)`. + - Defer Xbox link; allow gameplay immediately. Offer linking again next time. + +#### Notes +- Always fetch and display enough context to inform the player's decision. +- Record telemetry for reconciliation outcomes to improve prompts and defaults over time. + +### Strategy 2 flow diagram + +The following diagram shows the complete decision tree. Every path converges on a single terminal node where the player reaches a playable state. + +![Strategy 2 flow diagram showing the complete decision tree from Steam local user creation through sign-in, account linking, and reconciliation paths.](media/strategy2-flow.svg) + +## See also + +- [PlayFab Game Saves overview](overview.md) +- [Game Saves quickstart](quickstart.md) +- [Game Saves conflicts](conflicts.md) +- [Token expiration and relogin](../../sdks/c/relogin.md) \ No newline at end of file diff --git a/playfab-docs/player-progression/game-saves/media/mermaid-learn.json b/playfab-docs/player-progression/game-saves/media/mermaid-learn.json new file mode 100644 index 000000000..3cda37894 --- /dev/null +++ b/playfab-docs/player-progression/game-saves/media/mermaid-learn.json @@ -0,0 +1,17 @@ +{ + "theme": "base", + "themeVariables": { + "primaryColor": "#e8f0fe", + "primaryTextColor": "#1a1a1a", + "primaryBorderColor": "#4a86c8", + "lineColor": "#5a6a7a", + "secondaryColor": "#f0f4f0", + "tertiaryColor": "#fff8e8", + "edgeLabelBackground": "#f0f4f8", + "fontFamily": "Segoe UI, sans-serif", + "fontSize": "14px" + }, + "flowchart": { + "padding": 16 + } +} diff --git a/playfab-docs/player-progression/game-saves/media/strategy2-flow.mmd b/playfab-docs/player-progression/game-saves/media/strategy2-flow.mmd new file mode 100644 index 000000000..8a5442274 --- /dev/null +++ b/playfab-docs/player-progression/game-saves/media/strategy2-flow.mmd @@ -0,0 +1,44 @@ +flowchart TD + A["Create Steam local user + PFLocalUserCreateHandleWithSteamUser"] --> B["Try Steam sign-in + createAccount=false"] + + B -->|"  Success  "| C["Check linked identities + GetAccountInfo"] + B -->|"  E_PF_ACCOUNT_NOT_FOUND  "| D{Player choice} + + C -->|"  Xbox/MSA linked  "| PLAY[Play online] + C -->|"  Not linked  "| E["Prompt to link Xbox/MSA + non-blocking"] + E -->|"  Player agrees  "| LATE[BeginLateLink] + E -->|"  Player defers  "| PLAY + + D -->|"  Xbox bootstrap  "| F["Try Xbox sign-in + createAccount=false"] + D -->|"  Steam-only  "| G["Steam sign-in + createAccount=true"] --> PLAY + + F -->|"  E_PF_ACCOUNT_NOT_FOUND  "| H["Create Xbox account + createAccount=true"] + F -->|"  Existing account  "| LATE + + H --> I[Link Steam to Xbox account] --> J[Rebind Steam local user] --> PLAY + + LATE --> K[Try link Xbox to Steam account] + K -->|"  Success  "| PLAY + K -->|"  Conflict  "| L[Xbox sign-in to get entity] + L --> M["RunReconciliation + fetch account info + show UI"] + + M -->|"  Keep Xbox progress  "| N0{Xbox entity has + different Steam?} + N0 -->|"  Yes  "| N1["Unlink old Steam + UnlinkSteamAccount"] + N1 --> N2["Link current Steam + to Xbox account"] + N0 -->|"  No  "| N2 + N2 -->|"  LinkedAccountAlreadyClaimed  "| N3["Retry with + forceLink=true"] + N3 --> O + N2 -->|"  Success  "| O[Rebind Steam local user] --> PLAY + M -->|"  Keep Steam progress  "| P[Defer Xbox link] --> PLAY \ No newline at end of file diff --git a/playfab-docs/player-progression/game-saves/media/strategy2-flow.svg b/playfab-docs/player-progression/game-saves/media/strategy2-flow.svg new file mode 100644 index 000000000..a36ea3a77 --- /dev/null +++ b/playfab-docs/player-progression/game-saves/media/strategy2-flow.svg @@ -0,0 +1 @@ +

  Success  

  E_PF_ACCOUNT_NOT_FOUND  

  Xbox/MSA linked  

  Not linked  

  Player agrees  

  Player defers  

  Xbox bootstrap  

  Steam-only  

  E_PF_ACCOUNT_NOT_FOUND  

  Existing account  

  Success  

  Conflict  

  Keep Xbox progress  

  Yes  

  No  

  LinkedAccountAlreadyClaimed  

  Success  

  Keep Steam progress  

Create Steam local user
PFLocalUserCreateHandleWithSteamUser

Try Steam sign-in
createAccount=false

Check linked identities
GetAccountInfo

Player choice

Play online

Prompt to link Xbox/MSA
non-blocking

BeginLateLink

Try Xbox sign-in
createAccount=false

Steam sign-in
createAccount=true

Create Xbox account
createAccount=true

Link Steam to Xbox account

Rebind Steam local user

Try link Xbox to Steam account

Xbox sign-in to get entity

RunReconciliation
fetch account info + show UI

Xbox entity has
different Steam?

Unlink old Steam
UnlinkSteamAccount

Link current Steam
to Xbox account

Retry with
forceLink=true

Rebind Steam local user

Defer Xbox link

\ No newline at end of file diff --git a/playfab-docs/player-progression/game-saves/toc.yml b/playfab-docs/player-progression/game-saves/toc.yml index 77d316fe7..058ee68ea 100644 --- a/playfab-docs/player-progression/game-saves/toc.yml +++ b/playfab-docs/player-progression/game-saves/toc.yml @@ -6,6 +6,8 @@ items: href: onboarding.md - name: Quickstart href: quickstart.md +- name: Account Linking + href: linking.md - name: October 2025 GDK Implementation href: october-2025-gdk-changes.md - name: Steam Deck Implementation diff --git a/playfab-docs/pricing/Meters/meters.md b/playfab-docs/pricing/Meters/meters.md index 63afe42a9..a484457dd 100644 --- a/playfab-docs/pricing/Meters/meters.md +++ b/playfab-docs/pricing/Meters/meters.md @@ -114,11 +114,11 @@ You can also use this [Party pricing calculator](https://playfab.com/party-calcu ### Matchmaking and Lobby -PlayFab Matchmaking and Lobby are highly-customizable, proven solutions for building and orchestrating player groupings during a game session. Players can receive real-time notifications so they can quickly react when there are relevant updates in the Matchmaking or Lobby service. +PlayFab Matchmaking and Lobby are highly-customizable, proven solutions for building and orchestrating player groupings during a game session. Players can receive real-time messages so they can quickly react when there are relevant updates in the Matchmaking or Lobby service. * **MatchmakingRequests**: One Matchmaking Request is metered for each call to a [Matchmaking API](/rest/api/playfab/multiplayer/matchmaking) endpoint. * **LobbyRequests**: One Lobby Request is metered for each call to a [Lobby API](/rest/api/playfab/multiplayer/lobby) endpoint. -* **Messages**: Metered by the number of message recipients. [Lobby and Matchmaking real-time notifications](../../multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md) are dispatched to subscribed clients upon important events such as receiving invites, joining and updating lobbies, or finding matches. +* **Messages**: Metered by the number of message recipients. [Lobby and Matchmaking real-time messages](../../multiplayer/lobby/lobby-and-matchmaking-real-time-messages.md) are dispatched to subscribed clients upon important events such as receiving invites, joining and updating lobbies, or finding matches. ### Leaderboard diff --git a/playfab-docs/release-notes/2016.md b/playfab-docs/release-notes/2016.md index d7974a669..94d3380d4 100644 --- a/playfab-docs/release-notes/2016.md +++ b/playfab-docs/release-notes/2016.md @@ -122,8 +122,8 @@ Date: October 16, 2016 ### API changes - **New PlayStream events:** - - ~~`gamelobby_started`~~ (UPDATED: This is deprecated. See [Lobby-Matchmaking-Notifications](../multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md)) - - ~~`gamelobby_ended`~~(UPDATED: This is deprecated. See [Lobby-Matchmaking-Notifications](../multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md)) + - ~~`gamelobby_started`~~ (UPDATED: This is deprecated. See [Lobby-Matchmaking-Messages](../multiplayer/lobby/lobby-and-matchmaking-real-time-messages.md)) + - ~~`gamelobby_ended`~~(UPDATED: This is deprecated. See [Lobby-Matchmaking-Messages](../multiplayer/lobby/lobby-and-matchmaking-real-time-messages.md)) - [Client/AttributeInstall](xref:titleid.playfabapi.com.client.advertising.attributeinstall) request deprecated `Android_Id` and converted to `Adid`. All SDKs had some internal login hooks updated to account for this. This isn't a breaking change, because it's intended to use Google-AdvertisingId (Adid), and using the Android DeviceId here doesn't work properly. This change is for clarity and consistency - For the GitHub add-on, revisions to CloudScript no longer immediately go live. Instead a new revision is made, and you make it live via Game Manager - The default `helloWorld` CloudScript function described in this doc: [CloudScript quickstart](../live-service-management/service-gateway/automation/cloudscript/quickstart.md) was out of date. Updated the document to more closely match the current version (This is only relevant to new title creation) @@ -461,8 +461,8 @@ Date: July 31, 2016 - **New PlayStream Events** - - ~~[session_started]~~(UPDATED: This is deprecated. See [Lobby-Matchmaking-Notifications](../multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md)) - - ~~[session_ended]~~(UPDATED: This is deprecated. See [Lobby-Matchmaking-Notifications](../multiplayer/lobby/lobby-and-matchmaking-real-time-notifications.md)) + - ~~[session_started]~~(UPDATED: This is deprecated. See [Lobby-Matchmaking-Messages](../multiplayer/lobby/lobby-and-matchmaking-real-time-messages.md)) + - ~~[session_ended]~~(UPDATED: This is deprecated. See [Lobby-Matchmaking-Messages](../multiplayer/lobby/lobby-and-matchmaking-real-time-messages.md)) - Minor documentation updates. ## 160726 diff --git a/playfab-docs/release-notes/index.md b/playfab-docs/release-notes/index.md index a1da27b06..b6d3b0bba 100644 --- a/playfab-docs/release-notes/index.md +++ b/playfab-docs/release-notes/index.md @@ -14,6 +14,16 @@ ms.localizationpriority: medium > [!NOTE] > For release notes about service releases and product updates, see the [release notes](https://github.com/PlayFab/PlayFab/releases) section on [PlayFab's public GitHub repository](https://github.com/PlayFab/PlayFab) +## 260313 + +Date: March 13, 2026 + + - Renamed the `GetPlayersInSegmentDeprecated` error code to `GetPlayersInSegmentRetired` + - Updated the `GetFriendsList` documentation in the Client and Server APIs to clarify Xbox friend's behavior + - Updated the `FindFriendLobbies` documentation in the Multiplayer API to clarify mutual friends requirement + - Added the `ProductDisabledForTitle` error code to multiple calls across the Client, Server, Admin, and Experimentation APIs + - Added error codes for new service errors + ## 260227 Date: February 27, 2026 From ef10ee862482083b3d09142ed3fa8fe1a5c3eba3 Mon Sep 17 00:00:00 2001 From: "learn-build-service-prod[bot]" <113403604+learn-build-service-prod[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 11:51:45 -0700 Subject: [PATCH 73/76] =?UTF-8?q?Auto=20Publish=20=E2=80=93=20main=20to=20?= =?UTF-8?q?live=20-=202026-03-24=2017:01=20UTC=20(#2868)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initialize Docs repository: https://github.com/MicrosoftDocs/playfab-docs-pr of branch main * [PubSub] Rename "Notifications" to "Messages" in PubSub docs. Also add a note for PubSub clients about ensuring they set KeepAliveInterval (#2843) * [PubSub] Rename "Notifications" to "Messages" in PubSub docs. Also add a note for PubSub clients about ensuring they set KeepAliveInterval * Fix Acrolinx grammar issues to meet minimum 80 score - Fix possessive 'it's' -> 'its' in mpintro.md - Replace 'aka' with 'also known as' in mpintro.md - Replace 'e.g.' with 'for example' in mpintro.md - Fix 'ex:' -> 'for example' and missing 'be' in signalr-hub.md - Expand 'you're' -> 'you are' in signalr-hub.md - Fix double space and contractions in start-or-recover-session-response.md - Replace 'don't' with 'do not' across all 18 PubSub NOTE blocks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * retrigger checks * retrigger Acrolinx checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * acrolinx updates * acrolinx clarity --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update (#2841) Co-authored-by: OpenPublishing.Build * PlayStream Event Documentation Updates: Experimentation, PlayStream (actions), Segmentation, TargetedConfiguration (player churn) (#2826) * Add Experimentation events * Add Segmentation events * Add PlayStream actions events * Add player churn event * Fix typo in index.md * Fix some typos in index.md * move player-action-executed back to Player folder * Update table of contents with new event docs in this PR. * Game Saves linking doc (#2761) * Initial draft of linking doc * MS learn requirements * Fixing invalid apostrophe characters * Fixing a few header levels * Added suggested changes to sample code * Misc fixes * Fix correctness issues and Acrolinx style in linking.md - Replace XAsyncGetStatus with PFAuthenticationLoginWithXUserGetResultSize in Strategy 2 sample (XAsyncGetStatus doesn't return PF error codes) - Add note about RETURN_IF_FAILED in void XAsyncBlock callbacks - Fix typo: defered -> deferred - Acrolinx: login -> sign-in for user actions, add contractions, remove filler words, fix future tense, expand MSA acronym - Convert blockquote to [!TIP] callout for player-facing wording note - Add [!IMPORTANT] callout warning about static XAsyncBlock lifetime - Add caller-responsibility comments for heap-allocated context structs - Add See also section with links to related docs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refactor Strategy 2 sample code and add flow diagram - Extract helper functions: RunReconciliation, BeginLateLink, BootstrapViaXbox, CheckLinkStatusAndPrompt - Reduce max nesting from 7 levels to 4; RunStrategy2Flow drops from ~140 lines to ~55 lines - Add forward declarations and banner comments for each helper - Add Mermaid flowchart showing the complete Strategy 2 decision tree between the prose walkthrough and the sample code Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Mermaid diagram syntax for Learn and VSCode rendering Remove HTML br tags, Unicode special characters, and parentheses from Mermaid node/edge labels that prevented rendering. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Replace Mermaid code block with rendered SVG diagram Learn doesn't support Mermaid natively, so render the Strategy 2 flow diagram as an SVG image. The .mmd source is kept alongside the SVG in media/ for future regeneration via mmdc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove Strategy 2 sample code and polish flow diagram - Remove the ~330-line Strategy 2 C++ sample. The prose walkthrough and flow diagram provide sufficient guidance; a full working sample should be added separately. - Restyle the SVG diagram with a custom Learn-friendly theme (soft blue nodes, Segoe UI font) and add horizontal padding to edge labels. - Add mermaid-learn.json config for future diagram regeneration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix diagram description: single terminal node, not multiple Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Minor Acrolinx fixes in Strategy 1 prose - Add missing comma after introductory clause - 'will require' -> 'requires', 'can just go' -> 'can go' (present tense) - 'different than' -> 'different from' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add verification callout for cross-platform link on returning players When a title requires the cross-platform identity to match the currently signed-in user, a successful platform login alone isn't sufficient. Added a NOTE callout after the happy path advising titles to verify the link via GetAccountInfo. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix forceLink guidance to distinguish AccountAlreadyLinked vs LinkedAccountAlreadyClaimed forceLink only resolves LinkedAccountAlreadyClaimed (platform account claimed by another entity). It does not resolve AccountAlreadyLinked (entity already has a different platform account linked). The latter requires an explicit Unlink call before re-linking. Updated prose, sample code comments, and mermaid diagram to reflect the correct two-error handling. Also fixed SVG background to transparent for dark mode support. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review feedback: style and terminology fixes - Convert all headings from title case to sentence case (DocuMentor rule) - Replace 'e.g.' with 'for example,' (8 instances) - Hyphenate 'first-party' and 'free-to-play' as compound adjectives - Fix 'OpenId Connect' to 'OpenID Connect' - Add backticks around LoginWithXbox and LoginWithOpenIdConnect - Use contraction 'wasn''t' instead of 'was not' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix sample code and error names verified against PlayFab.C source Verified linking.md claims against PlayFab.C SDK headers using the AGENTS.md bootstrap context added to PlayFab.C. Four issues found and fixed: 1. PFAccountManagementClientLinkSteamAccountGetResult does not exist - LinkSteamAccount is a void async op. Replaced with XAsyncGetStatus. 2. forceLink field is bool const* (optional pointer), not bool. The previous code set the pointer to null via 'false', which accidentally worked but would crash if set to 'true'. Replaced with commented-out pointer pattern showing correct usage. 3. Added ticketIsServiceSpecific field (required when using GetAuthTicketForWebApi with AzurePlayFab identity string). 4. Replaced service-side error string names (LinkedAccountAlreadyClaimed, AccountAlreadyLinked) with SDK HRESULT constants (E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED, E_PF_ACCOUNT_ALREADY_LINKED) throughout prose, tables, and code comments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jason Sandlin * Update Playfab release notes for 260313 (#2854) * Update Playfab release notes for 260313 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --------- Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Kkline matchupdates (#2847) * Add files via upload * Add section on rule weight in matchmaking * Update Weight description in config-queues.md Added a reference to 'Understanding rule weight in matchmaking' for clarity. * Add files via upload * Add matchmaking dynamic partitioning to TOC * Revise matchmaking dynamic partitioning documentation Revised version that includes less internal specifics. * Add section for lobby lifetime and expiration * Add files via upload * Fix typo in lobby and matchmaking documentation * Fix grammatical error in lobby ownership description Corrected grammatical error in the description of lobby ownership categories. * Clarify filter operators in find-lobbies.md * Revise matchmaking partitioning to include scaling details Changed some of the text to remove internal service specifics * Rename 'Matchmaking dynamic partitioning' to 'How matchmaking scales under load' * TEST AI acrolinx fixes (#2858) * acrolinx fixes * revert 'dust bowl' to 'dustbowl' revert 'dust bowl' to 'dustbowl' --------- Co-authored-by: edigonzales-microsoft * Add documentation for toxmod (#2848) * Add documentation for toxmod * resolve comments --------- Co-authored-by: edigonzales-microsoft * Add Linux process-based server asset packaging docs (#2861) * Add Linux process-based server asset packaging docs - Broaden page title from 'Linux container images' to 'Linux Builds' - Add new section: Packaging assets for Linux process-based servers - Document tar.gz top-level wrapper directory requirement - Document that zip does not preserve Unix file permissions - Add correct/incorrect archive structure examples - Add start command guidance for process mode - Add quick reference table (zip vs tar.gz) - Add Linux VM base image info (Ubuntu 22.04) and pre-installed libraries - Add warning about symlinks/hard links being silently skipped - Add Linux process mode limitations (crash dumps, process isolation) - Update toc.yml nav entry to match new title - Update cross-references in 4 other pages to use new title Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Acrolinx clarity issues in deploying-linux-based-builds.md - Replace present perfect tense with present tense - Expand acronyms on first use (VMs, LTS, SDKs) - Remove directional terms (below, above, on the right) - Use nouns after demonstrative pronouns (this, that) - Simplify word choices (additional -> other/extra/more) - Split complex sentences for readability - Remove filler phrases - Reword goal-before-action for docker push instruction Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fixes --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove toxmod-related notes (#2864) * I believe this fixes some compile errors in the c# example for entity… (#2801) * I believe this fixes some compile errors in the c# example for entity-files. * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --------- Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Co-authored-by: Anthony Nguyen <108492711+antnguyen89@users.noreply.github.com> Co-authored-by: edigonzales-microsoft * ADO 61124898 - article revision (data-connection 'overview' and 'quickstart') (#2833) * ADO 61124898 - article revision (data-connection 'overview' and 'quickstart') * Update per Rachel's feedback and minor punctuation fixes. * PR 2833 requested changes and build update * Added references to AWS S3 in overview + quickstart for Data Connections --------- Co-authored-by: v-foxval@microsoft.com Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Co-authored-by: Rachel Akisada <87677950+raakisad@users.noreply.github.com> --------- Co-authored-by: v-alje <4665434+v-alje@users.noreply.github.com> Co-authored-by: Warren Alpert <1860902+WarrenAlpert@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: learn-build-service-prod[bot] <113403604+learn-build-service-prod[bot]@users.noreply.github.com> Co-authored-by: OpenPublishing.Build Co-authored-by: Joel Kucera Co-authored-by: Andy McCalib Co-authored-by: Jason Sandlin Co-authored-by: Steven Rojas Lizano Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Co-authored-by: Keith Kline <43284035+keithrkline@users.noreply.github.com> Co-authored-by: edigonzales-microsoft Co-authored-by: yuehanlin <99760142+yuehanlin@users.noreply.github.com> Co-authored-by: Dimitris-Ilias Gkanatsios Co-authored-by: Ronald Harding Co-authored-by: Anthony Nguyen <108492711+antnguyen89@users.noreply.github.com> Co-authored-by: Fox Valorguard <218149361+foxvalo@users.noreply.github.com> Co-authored-by: v-foxval@microsoft.com Co-authored-by: Rachel Akisada <87677950+raakisad@users.noreply.github.com> --- .../export-data/data-connection-overview.md | 28 +-- .../export-data/data-connection-quickstart.md | 53 ++-- .../entities/entity-files.md | 27 +- .../multiplayer/lobby/create-a-lobby.md | 2 +- .../multiplayer/lobby/find-lobbies.md | 8 +- .../lobby/lobby-and-matchmaking.md | 48 ++-- playfab-docs/multiplayer/lobby/lobby-ttl.md | 119 +++++++++ playfab-docs/multiplayer/lobby/toc.yml | 2 + .../multiplayer/matchmaking/config-queues.md | 60 ++--- .../matchmaking/matchmaking-partition.md | 48 ++++ .../multiplayer/matchmaking/rule-weights.md | 237 ++++++++++++++++++ playfab-docs/multiplayer/matchmaking/toc.yml | 4 + .../servers/author-a-game-server-build.md | 4 +- .../multiplayer/servers/build-definition.md | 2 +- .../servers/deploy-using-game-manager.md | 2 +- .../servers/deploy-using-powershell-api.md | 4 +- .../servers/deploying-linux-based-builds.md | 107 ++++++-- playfab-docs/multiplayer/servers/toc.yml | 2 +- 18 files changed, 617 insertions(+), 140 deletions(-) create mode 100644 playfab-docs/multiplayer/lobby/lobby-ttl.md create mode 100644 playfab-docs/multiplayer/matchmaking/matchmaking-partition.md create mode 100644 playfab-docs/multiplayer/matchmaking/rule-weights.md diff --git a/playfab-docs/data-analytics/export-data/data-connection-overview.md b/playfab-docs/data-analytics/export-data/data-connection-overview.md index 715a51788..488427553 100644 --- a/playfab-docs/data-analytics/export-data/data-connection-overview.md +++ b/playfab-docs/data-analytics/export-data/data-connection-overview.md @@ -1,7 +1,7 @@ --- -title: Data connections - Overview +title: Data Connections - Overview author: sofiamarinv -description: Data connections +description: Data Connections ms.author: sofiamarin ms.date: 11/27/2023 ms.topic: article @@ -10,35 +10,35 @@ keywords: playfab, data connections, byos, connections, event ingestion ms.localizationpriority: medium --- -# Data connections +# Data Connections -**Data connections** enables the continuous near real-time distribution and ingestion of PlayStream and Telemetry data into your chosen and authorized storage resource in your Azure subscription. Today it works with Azure Blob Storage, Azure Data Explorer (ADX) and Microsoft Fabric KQL databases. +**Data Connections** enables continuous, near-real-time ingestion of PlayStream and Telemetry data into your authorized storage resource in your Azure subscription. This feature works with Azure Blob Storage, Azure Data Explorer (ADX), Microsoft Fabric KQL databases, and Amazon Web Services S3. -It provides control of your data in your storage account with less than 5-minute data ingestion latency. The architecture is designed for better batch processing that facilitates Parquet files in blob storage with the highest throughput, low storage cost, and most flexibility. In case of failure in data distribution, a built-in automatic retry mechanism is in place to ensure data quality. +It provides control of your data in your storage account with less than five-minute data ingestion latency. The architecture is designed for batch processing and supports Parquet files in Blob Storage with higher throughput, lower storage cost, and greater flexibility. In case of data distribution failure, a built-in automatic retry mechanism helps ensure data is delivered successfully. -You can get started with data connections for event ingestion using PlayFab’s Game Manager portal or scalable APIs. +You can get started with Data Connections for event ingestion by using PlayFab’s Game Manager portal or scalable APIs. > [!Note] -> Although you can use either ADX, Blob or Fabric KQL, these have different potential use cases. Blob may be preferred if you are leveraging synapse for ML modelling and batch processing, while ADX supports ad-hoc querying and real-time debugging of your live services with analytics. +> Although you can use either ADX, Blob, or Fabric KQL, these options have different potential use cases. You might prefer Blob if you’re using Synapse for ML modeling and batch processing, while ADX supports ad-hoc analytics, querying, and real-time debugging of live services. -![Screenshot of data connections Overview](media/data-connections-overview.png "Data Connections Overview") +![Screenshot of Data Connections Overview](media/data-connections-overview.png "Data Connections Overview") ## Why do you need it? -Data connections is the replacement for the Event Export and Export to S3 features that currently PlayFab supports. Data connections allow for faster export in preferred formats for offline processing. You get to bring your storage account for data to be ingested and distributed. That means you get to manage and control the encryption-at-rest policy, the lifetime management policy, and network access. The billing becomes simplified as the costs associated with that storage account are accounted for centrally in your all-up Azure account billing. +Data Connections replaces the Event Export and Export to S3 features that PlayFab currently supports. It allows for faster export in supported formats for offline processing. You provide the storage account where the data is ingested and delivered. That means you control encryption at rest, lifecycle management, and network access. Billing is simplified because the storage costs are included centrally in your overall Azure account billing. ### Azure Blob Data Connection -The data is readily available in Parquet blob format. Parquet is a column-oriented data file format designed for efficient data storage and retrieval. It provides efficient data compression and encoding schemes with enhanced performance to handle complex data in bulk, resulting in low latency, higher throughput, and low cost of data storage. It's designed to be a common interchange format for both batch and interactive workloads. Thus, data connections enables your endeavors for custom advanced analytics and reporting, to run ad-hoc queries in a cost-optimized manner. +The data is readily available in Parquet blob format. Parquet is a column-oriented data file format designed for efficient data storage and retrieval. It provides efficient data compression and encoding schemes with enhanced performance to handle complex data in bulk, resulting in low latency, higher throughput, and low cost of data storage. It's designed to be a common interchange format for both batch and interactive workloads. This makes Blob Storage a good fit for offline processing and cost-optimized analytics and reporting (including ad-hoc queries over stored files). ### Azure Data Explorer Data Connection -Data Connections allows you to export to Azure Data Explorer for near-real time ingestion and distribution of your data. Azure Data Explorer can query millions of records in a few seconds enabling you to gain invaluable insights and make informed decisions swiftly and efficiently. +Data Connections allows you to export to Azure Data Explorer for near-real-time ingestion and distribution of your data. Azure Data Explorer can query millions of records in a few seconds, enabling you to gain invaluable insights and make informed decisions swiftly and efficiently. -For more optimized cost and data control, you can make use of data connections with [Event Sampling](event-sampling-overview.md) - Sampling enables you to configure the percentage of events data that you want to receive. +For more optimized cost and data control, you can make use of Data Connections with [Event Sampling](event-sampling-overview.md). Sampling enables you to configure the percentage of events data that you want to receive. ### Microsoft Fabric KQL database Data Connection -You can utilize PlayFab's Data Connections service to distribute game events to Real-Time Analytics (RTA) databases, allowing you to generate near-real-time analytics and insights in Power BI or through KQL queries on your Microsoft Fabric workspace. +Use PlayFab’s Data Connections to send game events to Real-Time Analytics (RTA) databases, so you can generate near-real-time insights in Power BI or run KQL queries in your Microsoft Fabric workspace. ### Amazon AWS S3 Data Connection (PREVIEW) -The AWS S3 Data Connection provides a secure, scalable way to stream your PlayFab telemetry and event data directly into your own Amazon S3 bucket. Designed for reliability and high throughput workloads, it uses a robust pipeline to validate, transport, and land game data in an open, analytics ready format. By bringing your own AWS storage and IAM roles, you retain full control of data governance, encryption, access policies, lifecycle management, and cost visibility while enabling downstream workflows such as BI reporting, machine learning, and largescale data processing in your AWS environment. \ No newline at end of file +The AWS S3 Data Connection provides a secure, scalable way to stream your PlayFab telemetry and event data directly into your own Amazon S3 bucket. Designed for reliability and high throughput workloads, it uses a robust pipeline to validate, transport, and land game data in an open, analytics ready format. By using your own AWS storage and IAM roles, you retain control over data governance, encryption, access policies, lifecycle management, and cost visibility. This also enables downstream workflows such as BI reporting, machine learning, and large-scale data processing in your AWS environment. \ No newline at end of file diff --git a/playfab-docs/data-analytics/export-data/data-connection-quickstart.md b/playfab-docs/data-analytics/export-data/data-connection-quickstart.md index 185c7a1dc..6be35c8d8 100644 --- a/playfab-docs/data-analytics/export-data/data-connection-quickstart.md +++ b/playfab-docs/data-analytics/export-data/data-connection-quickstart.md @@ -6,24 +6,25 @@ ms.author: sofiamarin ms.date: 11/27/2023 ms.topic: article ms.service: azure-playfab -keywords: playfab, data connections, byos, connections, event ingestion, bring your own stoarge +keywords: playfab, data connections, byos, connections, event ingestion, bring your own storage ms.localizationpriority: medium --- # Data Connections quickstart ## Prerequisites -- For Data Connections, you need an Azure subscription and a storage account. -- For PlayFab to ingest data in your storage account, container details along with authorization using a SAS token are required. To create a SAS token using Microsoft Azure portal, follow the steps below. +- For Data Connections, you need an Azure or Amazon subscription and a storage account. +- For PlayFab to ingest data in your storage account, you need container details along with authorization using a SAS token. +- To create a SAS token using Microsoft Azure portal, follow the steps in the next section. ## Create a Data Connection -A Connection is created to integrate your storage resource with PlayFab and retrieve the PlayStream and Telemetry data. You can configure up to three data connections in the “enabled (active)” state. +Create a connection to integrate your storage resource with PlayFab and retrieve the PlayStream and telemetry data. You can configure up to three data connections in the **enabled (active)** state. -### Azure Blog Storage +### Azure Blob Storage From the Game Manager: -- Navigate to your **Title** +- Go to your **Title** - Select **Data** from the menu on the left - Select **Data Connections** from the **Data** tabs - Select **New Connection**, new data connections configuration page is opened @@ -33,8 +34,8 @@ From the Game Manager: * Enter **Container Name** * Enter **SAS Token** as generated in the Azure portal - Select **Save** - * With the default check on **Enabled**, the connection between PlayFab and the customer’s resource is established once saved. - * With uncheck on **Enabled**, the connection between PlayFab and the customer’s resource is validated but not established until saved. + * By using the default check on **Enabled**, the connection between PlayFab and your resource is established once saved. + * By using uncheck on **Enabled**, the connection between PlayFab and your resource is validated but not established until saved. ![Screenshot of Create Data Connection](media/create-data-connection.png "Create Data Connection") @@ -42,12 +43,12 @@ From the Game Manager: From PlayFab Game Manager: -- Navigate to your **Title** +- Go to your **Title** - Select **Data** from the menu on the left - Select **Data Connections** from the **Data** tabs - Select **New Connection**, new data connections configuration page is opened - On the **Destination type** dropdown, select the **Fabric KQL Database** option -- Give your **Data Connection** a name on the **Name** field +- Enter a name for your **Data Connection** in the **Name** field - Make sure the **Enabled** box is checked - Go to [Microsoft Fabric](https://msit.powerbi.com/home) - Select **Workspaces** on the left panel and select **Your Workspace** @@ -56,17 +57,17 @@ From PlayFab Game Manager: - Go back to Data Connections on PlayFab's Game Manager - Paste the **Query URI** you got from Fabric into the **Ingestion URI** field - In the **Database** field, enter the name of the **KQL Database** you created in Fabric -- Fill the **Table** field with a significant name. Example: **Events** +- Fill the **Table** field with a significant name (for example, **Events**) > [!Note] > To optimize your use of a Fabric KQL Data Connection and gain valuable insights into your game data, follow the tutorial on PlayFab and Microsoft Fabric Real-Time Analytics (RTA) for game creators: [PlayFab and Microsoft Fabric Real-Time Analytics (RTA) for game creators](../learn-data/reports/real-time-analytics-tutorial.md) ### Amazon Web Services S3 (PREVIEW) From PlayFab Game Manager: -- Navigate to your Title +- Navigate to your title - Select Data from the menu on the left - Select Data Connections from the Data tabs -- Select New Connection, new data connections configuration page is opened +- Select New Connection; the new data connections configuration page opens - On the Destination type dropdown, select the AWS S3 option - Give your Data Connection a name on the Name field - Make sure the Enabled box is checked @@ -75,22 +76,22 @@ From PlayFab Game Manager: * Navigate to Identity Providers * Select Add Provider * Select OpenID Connect - * In the forum: - * For the provider URL, input https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/v2.0 - * For the Audience, input e12f8069-1801-4f61-9b5f-446d8bd57e8b - * Press Add Provider + * In the form: + * For the provider URL, input `https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/v2.0` + * For the Audience, input `e12f8069-1801-4f61-9b5f-446d8bd57e8b` + * Select Add Provider * Navigate back to IAM * Navigate to policies * Select Create policy - * In the forum: - * Select JSON to switch to the JSON view + * In the form: + * Select JSON to switch to the JSON view. * Input the following policy: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::test/*", "arn:aws:s3:::test" ] } ] } * Select Next - * Enter a name for your policy – take note of it for later + * Enter a name for your policy – take note of it for later * Select Create policy * Navigate back to IAM * Navigate to Roles - * In the forum: + * In the form: * Select Web Identity * From the Identity provider dropdown, select the previously registered https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/v2.0 provider * From the Audience dropdown, select the previously registered e12f8069-1801-4f61-9b5f-446d8bd57e8b audience @@ -104,17 +105,17 @@ From PlayFab Game Manager: * Select Properties * Scroll to the Tags section * Select Add new Tag - * In the forum: + * In the form: * For the key field, input playfab:titleids * For the value field, input your playfab TitleID * Select Save changes - * Ensure you have your S3 Bucket name, Role ARN, and S3 Bucket Region used in the prior steps. - * Enter those into the appropriate fields in the Game Manager. + * Ensure you have your S3 Bucket name, Role ARN, and S3 Bucket Region used in the prior steps + * Enter those into the appropriate fields in the Game Manager ## Manage connections -The Data Connections overview (landing) page displays the available connections categorized as **enabled** or **disabled** as a **status**. You can have up to 3 enabled connections to the blob storage account at any time. -The Data Connections overview page can also be used to manage connections by selecting any Connections’ ellipsis (…). Two actions comprising Edit and Delete can be taken on the connections. +The Data Connections overview (landing) page displays the available connections categorized as **enabled** or **disabled** as a **status**. You can have up to three enabled connections to the blob storage account at any time. +You can also use the Data Connections overview page to manage connections. Select the ellipsis (...) next to any connection. You can take two actions: **Edit** and **Delete**. ![Screenshot of Modify Data Connections](media/modify-data-connections.png "Modify Data Connections") diff --git a/playfab-docs/live-service-management/game-configuration/entities/entity-files.md b/playfab-docs/live-service-management/game-configuration/entities/entity-files.md index eaa91d877..6c66979f3 100644 --- a/playfab-docs/live-service-management/game-configuration/entities/entity-files.md +++ b/playfab-docs/live-service-management/game-configuration/entities/entity-files.md @@ -12,7 +12,7 @@ ms.localizationpriority: medium # Entity files -Entity files allow you to read and write files attached to an entity, in any format. The example shown below demonstrates a full entity-file loop, from logging in, to loading a file, and uploading a new file. +Entity files enable you to read and write files attached to an entity, in any format. The following example demonstrates a full entity-file loop, from signing in, to loading a file, and uploading a new file. ```csharp #if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API @@ -82,8 +82,7 @@ public class EntityFileExample : MonoBehaviour var request = new PlayFab.ClientModels.LoginWithCustomIDRequest { CustomId = SystemInfo.deviceUniqueIdentifier, - CreateAccount = true, - LoginTitlePlayerAccountEntity = true + CreateAccount = true }; PlayFabClientAPI.LoginWithCustomID(request, OnLogin, OnSharedFailure); } @@ -142,7 +141,7 @@ public class EntityFileExample : MonoBehaviour { if (error.Error == PlayFabErrorCode.EntityFileOperationPending) { - // This is an error you should handle when calling InitiateFileUploads, but your resolution path may vary + // This is an error you should handle when calling InitiateFileUploads, but your resolution path might vary GlobalFileLock += 1; // Start AbortFileUploads var request = new PlayFab.DataModels.AbortFileUploadsRequest { @@ -170,7 +169,7 @@ public class EntityFileExample : MonoBehaviour ); GlobalFileLock -= 1; // Finish InitiateFileUploads } - void FinalizeUpload() + void FinalizeUpload(byte[] body) // body is unused in this example { GlobalFileLock += 1; // Start FinalizeFileUploads var request = new PlayFab.DataModels.FinalizeFileUploadsRequest @@ -195,22 +194,22 @@ public class EntityFileExample : MonoBehaviour - `GlobalFileLock` is a simplistic way to avoid file collisions, specifically designed for this example. - Independent file actions won't cause any issues. - Each file action requires many steps and multiple API calls, so don't try to access the same file in multiple ways at the same time. - - If you're very careful, you won't need any locking mechanism. - - If you want to do something complicated, your locking mechanism may be much more complex. -- `OnGUI` is a very old (but very dense) way to build a Unity GUI entirely within script. + - If you're careful, you don't need any locking mechanism. + - If you want to do something complicated, your locking mechanism might be much more complex. +- `OnGUI` is an old, but very dense way, to build a Unity GUI entirely within script. - Your GUI will be much better, and game-specific. - All PlayFab features *first* require a login or authentication. -- `LoadAllFiles()` will do exactly as it says. For the current logged-in entity, load all file saved to PlayFab. - - This requires multiple steps: +- `LoadAllFiles()` does exactly as it says. For the current signed-in entity, it loads all files saved to PlayFab. + - This function requires multiple steps: - Asking PlayFab where the files are located, - And then downloading them separately. - `UploadFile(string fileName)` saves the file to the service for the entity. - - For simplicity, this example saves one file at a time, but files can be uploaded atomically in sets as well. - - The steps for this are: + - For simplicity, this example saves one file at a time, but you can upload files atomically in sets as well. + - The steps for this operation are: - Initialize an atomic upload operation, - Upload all files, - Finalize an atomic upload operation. - - The entity won't consider the file upload complete, nor reflect any changes to other callers until the atomic upload operation has been finalized successfully. + - The entity doesn't consider the file upload complete, nor reflect any changes to other callers until the atomic upload operation is finalized successfully. ## Game Manager and entities @@ -218,6 +217,6 @@ The Game Manager allows you to manipulate objects and files for players. The pla ![Game Manager - Entities - Player overview](media/tutorials/game-manager-entities-player-overview.png) -In addition, files and objects now have their own sections in the **Players** tab. +Also, the **Players** tab now includes separate sections for files and objects. ![Game Manager - Entities - Player Files and Objects](media/tutorials/game-manager-entities-player-files.png) diff --git a/playfab-docs/multiplayer/lobby/create-a-lobby.md b/playfab-docs/multiplayer/lobby/create-a-lobby.md index 66c0e8ad2..bf9cd0d9b 100644 --- a/playfab-docs/multiplayer/lobby/create-a-lobby.md +++ b/playfab-docs/multiplayer/lobby/create-a-lobby.md @@ -22,7 +22,7 @@ There are several ways a lobby can be created. * **By your game servers**: Your title's game servers can create lobbies and wait for players to join. These are server-owned lobbies. * **By matchmaking**: After a group of players form after matchmaking, a lobby is created as a holding place before the game starts. These are client-owned lobbies. -From a technical perspective, all lobbies are fall into two main categories based on ownership—server-owned and client-owned. To learn more, see [Owner requirements and privileges](owner-requirements-and-privileges.md). +From a technical perspective, all lobbies fall into two main categories based on ownership—server-owned and client-owned. To learn more, see [Owner requirements and privileges](owner-requirements-and-privileges.md). The general usage of PlayFab Lobby is to temporarily hold a group of players together. For commonly used applications of Lobby, see the [PlayFab Lobby overview](index.md). diff --git a/playfab-docs/multiplayer/lobby/find-lobbies.md b/playfab-docs/multiplayer/lobby/find-lobbies.md index 46c1e7440..99c1de369 100644 --- a/playfab-docs/multiplayer/lobby/find-lobbies.md +++ b/playfab-docs/multiplayer/lobby/find-lobbies.md @@ -63,7 +63,7 @@ These OData operators can be used to compose query strings. The operators are ca | le | less than or equal to | number_key2 le 10 | | gt | greater than | number_key3 gt 100 | | ge | greater than or equal to | number_key3 ge 100 | -| ne | ne | string_key1 ne 'CaptureTheFlag' | +| ne | not equal to | string_key1 ne 'CaptureTheFlag' | | and | and | string_key1 eq 'CaptureTheFlag' and number_key2 lt 10 | @@ -92,7 +92,7 @@ OData style string that contains sorting for this query in either ascending ("as |-----------------------------|---------------------------------------------------| | number_key1 asc | order by number search key ascending | | lobby/memberCount desc | order by number search key descending | -| distance(number_key1 = 5) | sort on distance from the given number | +| distance{number_key1 = 5} | sort on distance from the given number | | *default* | order by creation time descending | @@ -143,9 +143,9 @@ void FindGamesWithRuntimeQuery( filterString += " and "; filterString += PFLOBBY_SEARCH_KEY_COMPETITION_STYLE + std::string(" eq ") + "'" + COMPETITION_STYLE_RANKED + "'"; filterString += " and "; - filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" -ge ") + std::to_string(minimumSkill); + filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" ge ") + std::to_string(minimumSkill); filterString += " and "; - filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" -le ") + std::to_string(maximumSkill); + filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" le ") + std::to_string(maximumSkill); // Create sort string based on player's sort preference. std::string sortString; diff --git a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking.md b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking.md index 3fe6b63b8..aa4d438ec 100644 --- a/playfab-docs/multiplayer/lobby/lobby-and-matchmaking.md +++ b/playfab-docs/multiplayer/lobby/lobby-and-matchmaking.md @@ -13,25 +13,25 @@ ms.localizationpriority: medium # Use Lobby and Matchmaking Together -When designing multiplayer games, matchmaking and lobbies are often used together to help people form groups to play together. +When you design multiplayer games, matchmaking and lobbies are often used together to help people form groups to play together. -PlayFab Lobby and PlayFab Matchmaking helps you implement a wide variety of multiplayer scenarios. +PlayFab Lobby and PlayFab Matchmaking help you implement a wide variety of multiplayer scenarios. -This article describes the relationship between these two services and illustrates how they can be used together to implement a [game scenario](#example-scenario) specified below. +This article describes the relationship between these two services and shows how they can be used together to implement the following [game scenario](#example-scenario). ## Understand the relationship between Lobby and Matchmaking Lobby and Matchmaking work seamlessly together to create cohesive multiplayer matchmaking experience for your title. * Matchmaking gathers a set of players together looking to participate in a game session. -* After matchmaking has identified a set of players, Lobby provides them a communication medium to coordinate joining a game session together. +* After matchmaking identifies a set of players, Lobby provides them with a communication medium to coordinate joining a game session together. * Common scenarios for lobby include sharing game server connection information, sharing client IPs for peer-to-peer games, and sharing player configurations. ### Arranged lobbies -Titles can use "Arranged Lobbies" to support easily creating lobbies for your players which have been grouped together via matchmaking. +Titles can use "Arranged Lobbies" to support easily creating lobbies for your players that are grouped together via matchmaking. -After the matchmaking ticket has successfully matched a group of players, the matchmaking ticket will contain a __lobbyArrangementString__. Each player can then pass the arrangement string to __PFMultiplayerJoinArrangedLobby__ to join the same lobby. +After the matchmaking ticket successfully matches a group of players, the matchmaking ticket contains a __lobbyArrangementString__. Each player can then pass the arrangement string to __PFMultiplayerJoinArrangedLobby__ to join the same lobby. ## Example Scenario @@ -43,24 +43,24 @@ A player wants to play with other people. The player starts a multiplayer game, * The initial set of players is populated via matchmaking. * The lobby owner is able to invite friends to join. * When the required number of players are met, all players in the lobby receive a message asking if they're ready to start the game. They have one minute to respond. The game starts after all the players confirmed that they're ready to start game. -* If players in the lobby did not confirm their ready-to-play status, the lobby owner can remove them as inactive players and use matchmaking to find new players to quickly replace them. +* If players in the lobby didn't confirm their ready-to-play status, the lobby owner can remove them as inactive players and use matchmaking to find new players to quickly replace them. * When any player gets disconnected unexpectedly during the game, the title should find a new replacement for the dropped player through matchmaking using server backfill. -* When the game ends, all players return to the lobby. Players are awarded team achievements equally. They have the option to either stay to start another game together or leave the lobby. +* When the game ends, all players return to the lobby. Players are awarded team achievements equally. They can either stay to start another game together or leave the lobby. ### Implementation -This section describes how to use Matchmaking and Lobby to implement the above [design specifications](#design-specifications). +This section describes how to use Matchmaking and Lobby to implement the [design specifications](#design-specifications). -* [Create a matchmade lobby](#create-a-matchmade-lobby) +* [Create a match-made lobby](#create-a-match-made-lobby) * [Send invites to friends](#send-invites-to-friends) * [Allow people to find and join game](#allow-people-to-find-and-join-game) -* [Notify players to start game](#notify-players-to-start-game) +* [Get player confirmation to start game](#get-player-confirmation-to-start-game) * [Remove and replace inactive players](#remove-and-replace-inactive-players) * [Handle a finished game](#handle-a-finished-game) -### Create a matchmade lobby +### Create a match-made lobby -Create a public lobby for a group of matchmade players. +Create a public lobby for a group of match-made players. * Each player creates a matchmaking ticket with their specified matchmaking attributes. * To learn more, see [Specify ticket attributes](../matchmaking/ticket-attributes.md). @@ -68,9 +68,9 @@ Create a public lobby for a group of matchmade players. * Tickets are matched based on rules. * Rules can be defined in the matchmaking queue configuration. * To learn more, see [Configure matchmaking queues](../matchmaking/config-queues.md). -* After matchmaking, each player joins the matchmade lobby via the matchmaking ticket's __lobbyArrangementString__. +* After matchmaking, each player joins the match-made lobby via the matchmaking ticket's __lobbyArrangementString__. * When joining the arranged lobby, specify that the lobby's __accessPolicy__ is __Public__ to make the lobby open. - * See [Arranged lobbies](#arranged-lobbies) for more information. + * For more information, see [Arranged lobbies](#arranged-lobbies). * The first player to join the arranged lobby becomes the owner for the lobby. * The lobby properties can be used to specify which game map a game session intends to use. * For more information, see [Lobby properties](lobby-properties.md). @@ -88,15 +88,15 @@ Allow the lobby owner to select friends and send invites. ### Allow people to find and join game -Setup the lobby's search properties to allow other players to find it +Set up the lobby's search properties to allow other players to find it * Display all lobbies in your game UI. Your title should also provide a way to accept player's search terms. * Use __PFMultiplayerFindLobbies__ using the player's search parameters to return a list of lobbies that match the criteria. * After a player selects to join a game, use __PFMultiplayerJoinLobby__ to add the player to the game. -### Notify players to start game +### Get player confirmation to start game -Inform all players in the lobby that game is ready to start +Inform all players in the lobby that the game is ready to start * When the required number of players are in the lobby, display game UI to get players to confirm that they're ready to start play. * Allow the lobby owner to view these confirmation responses. @@ -105,19 +105,19 @@ Inform all players in the lobby that game is ready to start Lobby owner has the ability to remove inactive or disconnected players and initiate matchmaking to fill up the remaining spots -* If a player has discoonected or did not respond within the given set duration (one minute), use __PFLobbyForceRemoveMember__ to remove the player. -* The lobby owner will use __CreateServerBackfillTicket__ to create a matchmaking ticket. Tickets created using this API are given priority during searching. This is to minimize gameplay disruption. To learn more, see [Using server backfill tickets](../matchmaking/backfill-tickets.md). +* If a player disconnects or didn't respond within the given set duration (one minute), use __PFLobbyForceRemoveMember__ to remove the player. +* The lobby owner uses __CreateServerBackfillTicket__ to create a matchmaking ticket. Tickets created using this API are given priority during searching. This approach minimizes gameplay disruption. To learn more, see [Using server backfill tickets](../matchmaking/backfill-tickets.md). * After joining the backfill lobby, the game's lobby owner can share the original lobby's connection string with the new backfill players and they can join the original lobby. * Extend the game start time when appropriate. ### Handle a finished game -After the game has finished, all players return to the lobby screen to complete the game session. +After the game finishes, all players return to the lobby screen to complete the game session. -* Lobbies are transient so any data from the lobby which should be persisted should be retained by each player at this point. +* Lobbies are transient so any data from the lobby that should be persisted must be retained by each player at this point. * For example, some game scenarios may benefit from processing data stored in the member properties and turning that data into player achievements. -* Players who want to continue playing with the same group will stay in the lobby. -* Players who want to stop playing with the same group will leave the lobby with __PFLobbyLeave__ and restart the process with a new matchmaking group. +* Players who want to continue playing with the same group stay in the lobby. +* Players who want to stop playing with the same group leave the lobby with __PFLobbyLeave__ and restart the process with a new matchmaking group. ## See also diff --git a/playfab-docs/multiplayer/lobby/lobby-ttl.md b/playfab-docs/multiplayer/lobby/lobby-ttl.md new file mode 100644 index 000000000..a885c3136 --- /dev/null +++ b/playfab-docs/multiplayer/lobby/lobby-ttl.md @@ -0,0 +1,119 @@ +--- +title: Lobby lifetime and expiration +author: kkline +description: Learn about the lifetime of lobbies, including how different lobby types and connection states affect lobby expiration. +ms.author: kkline +ms.date: 02/27/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, multiplayer, lobby, matchmaking, ttl, lifetime, expiration +ms.localizationpriority: medium +--- + +# Lobby lifetime and expiration + +This article explains how lobbies expire and are deleted. Lobby lifetime depends on the lobby type, connection state, and member activity. Understanding these behaviors helps you design your game to avoid unexpected lobby loss and keep search results clean. + +## Overview + +PlayFab Lobbies are temporary groupings of players. Every lobby has a time to live (TTL) that determines when it will be automatically deleted if left idle. The TTL is reset whenever there's activity on the lobby, such as a member joining, leaving, or updating lobby data. + +The two most important factors that determine how long a lobby lives are: + +* **Lobby type**: Whether the lobby is client-owned or server-owned. +* **Connection state**: Whether members (and servers) are connected through real-time notifications. + +## Default lobby lifetime + +When a lobby is created, it's assigned a default TTL of **1 hour**. Each time the lobby is updated—through member joins, data updates, or other operations—the TTL is refreshed back to its full duration. + +For lobbies that use real-time notifications (connections), the TTL is extended to **4 hours** when a member connects. This longer TTL accounts for the fact that connected lobbies are actively monitored through the connection system and don't need to expire as quickly. + +> [!NOTE] +> The lobby TTL resets on every lobby operation. A lobby that is actively being used will not expire due to TTL alone. + +## How connections affect lobby lifetime + +Lobbies that use [real-time notifications](lobby-and-matchmaking-real-time-notifications.md) track member connections. The connection state of members directly impacts the lobby's lifetime and search visibility. + +### Connected lobbies + +When at least one member is connected to a client-owned lobby, the lobby remains searchable and has a maximum idle TTL of **4 hours**. As long as the lobby continues to receive updates or connection activity, the TTL continues to reset. + +### Disconnected lobbies + +When all members disconnect from a client-owned lobby, two things happen: + +1. **The lobby is hidden from search.** This prevents other players from discovering a lobby that may be abandoned. +2. **The lobby TTL is reduced to 1 minute.** The lobby enters a brief grace period before deletion. + +If a member reconnects during this grace period, the lobby is restored to full visibility and its TTL is extended back to 4 hours. + +## Lifetime behavior by lobby type + +Client-owned and server-owned lobbies have different expiration behaviors. + +### Client-owned lobbies + +| Scenario | Behavior | +|----------|----------| +| Active with connected members | TTL is 4 hours, reset on each operation. Lobby is searchable. | +| Active without connections | TTL is 1 hour, reset on each operation. Lobby is searchable. | +| Owner disconnects | Owner migration is triggered per the __ownerMigrationPolicy__. No direct impact on TTL. | +| All members disconnect | Lobby is hidden from search. TTL is reduced to 1 minute. | +| Member reconnects after all disconnected | Lobby becomes searchable again. TTL is restored to 4 hours. | +| Last member leaves | Lobby is deleted immediately. | + +For more information on what happens when an owner disconnects, see [Ownership changes](ownership-changes.md). + +### Server-owned lobbies + +| Scenario | Behavior | +|----------|----------| +| Active with connected server | TTL is 4 hours, reset on each operation. Lobby is searchable. | +| Active without connections | TTL is 1 hour, reset on each operation. Lobby is searchable. | +| Server-owner disconnects | Lobby is hidden from search. TTL is unaffected. | +| Server-owner reconnects | Lobby becomes searchable again. | +| All members disconnect | No action. The server is not a member, so member disconnections don't affect lobby lifetime. | +| Server leaves | The server can be replaced by another server claiming ownership. | + +> [!IMPORTANT] +> Server-owned lobbies are not deleted when all player members leave. Only the server owner can delete a server-owned lobby, or it will expire after the TTL runs out. + +## Extending lobby lifetime beyond the default TTL + +The 4-hour idle TTL is intended to be the maximum ordinary expected time a lobby would be left unattended. However, some scenarios—such as server-owned lobbies waiting for players to arrive—may require longer-lived lobbies. + +To keep a lobby alive beyond the default TTL, periodically update the lobby before the TTL expires. Any update operation resets the TTL. For example, a game server can update a lobby property at a regular interval to prevent the lobby from expiring. + +> [!NOTE] +> Any lobby operation resets the TTL, including updating lobby properties, member properties, or search properties. + +## Search visibility and expiration + +Lobby expiration and search visibility are closely related but distinct concepts. + +* **Hidden from search** means the lobby won't appear in [FindLobbies](find-lobbies.md) results, but it still exists and can be joined using the connection string. +* **Deleted** means the lobby no longer exists and can't be accessed. + +A lobby may be hidden from search but still alive during the grace period after all members disconnect. This design protects against temporary network disruptions—if members quickly reconnect, the lobby is restored without any data loss. + +## Summary + +| Factor | Value | +|--------|-------| +| Default TTL (no connections) | 1 hour | +| Default TTL (with connections) | 4 hours | +| TTL after all members disconnect (client-owned) | 1 minute before deletion | +| Client-owned lobby, last member leaves | Deleted immediately | +| Server-owned lobby, server disconnects | Hidden from search, TTL unaffected | +| TTL reset trigger | Any lobby operation (join, update, leave) | + +## See also + +* [Create a lobby](create-a-lobby.md) +* [Ownership changes](ownership-changes.md) +* [Game servers and lobbies](lobby-server-overview.md) +* [Lobby and matchmaking real-time notifications](lobby-and-matchmaking-real-time-notifications.md) +* [Lobby properties](lobby-properties.md) +* [Find lobbies](find-lobbies.md) diff --git a/playfab-docs/multiplayer/lobby/toc.yml b/playfab-docs/multiplayer/lobby/toc.yml index b65438525..3e14e2b0d 100644 --- a/playfab-docs/multiplayer/lobby/toc.yml +++ b/playfab-docs/multiplayer/lobby/toc.yml @@ -21,6 +21,8 @@ items: href: owner-requirements-and-privileges.md - name: Lobby ownership changes href: ownership-changes.md + - name: Lobby lifetime and expiration + href: lobby-ttl.md - name: Use lobby and matchmaking together href: lobby-and-matchmaking.md - name: Game servers and Lobbies diff --git a/playfab-docs/multiplayer/matchmaking/config-queues.md b/playfab-docs/multiplayer/matchmaking/config-queues.md index 1d71c9192..0984cd710 100644 --- a/playfab-docs/multiplayer/matchmaking/config-queues.md +++ b/playfab-docs/multiplayer/matchmaking/config-queues.md @@ -14,94 +14,94 @@ ms.localizationpriority: medium ## Overview -Match configuration centers around queues, which represent a place where tickets wait to be matched with each other. Each queue has some general configuration about what is required for a match. In addition, it can contain a set of rules which provide further restrictions on how tickets are matched together. +Match configuration centers around queues, which represent a place where tickets wait to be matched with each other. Each queue has some general configuration about what is required for a match. In addition, it can contain a set of rules that provide further restrictions on how tickets are matched together. ## Queue configuration -At the queue level, the configuration describes basic requirements regarding how tickets are matched inside a queue, as well as how you obtain statistics information about the queue. +At the queue level, the configuration describes basic requirements regarding how tickets are matched inside a queue and how you obtain statistics information about the queue. ### Queue name -The name for a specific queue. It is between 1 and 64 characters long (inclusive) and is case-sensitive. It is alpha-numeric, plus underscores and hyphens, and starts with a letter or number. Generally a queue name represents a way to play a game, such as "4v4CaptureTheFlag" or "UnrankedRace". When creating a matchmaking ticket, the queue name must be specified to identify which queue it should enter. +The name for a specific queue. It is between 1 and 64 characters long (inclusive) and is case-sensitive. It's alpha-numeric, plus underscores and hyphens, and starts with a letter or number. Generally a queue name represents a way to play a game, such as "4v4CaptureTheFlag" or "UnrankedRace". When you create a matchmaking ticket, you must specify the queue name to identify which queue it should enter. ### Match size -The range of players allowed in a match. The minimum match size must be greater than or equal to 2, and the maximum match size must be less than or equal to 100 (this limit is 32, if using teams). +The range of players allowed in a match. The minimum match size must be greater than or equal to two. The maximum match size must be less than or equal to 100. When using teams, this limit is 32. -In addition, even if a ticket alone already meets the minimum requirements for a match, it won't return a match found until it matches at least one other ticket. If a ticket already meets the maximum requirement for a match, however, it will be rejected. +In addition, even if a ticket alone already meets the minimum requirements for a match, it doesn't return a match found until it matches at least one other ticket. If a ticket already meets the maximum requirement for a match, however, it is rejected. ### Statistics available to players -This determines which queue statistics are exposed to players through the [GetQueueStatistics API](xref:titleid.playfabapi.com.multiplayer.matchmaking.getqueuestatistics). Servers always have access to all statistics. See the [Displaying queue statistics in your title](display-statistics.md) tutorial for more information. +This feature determines which queue statistics are exposed to players through the [GetQueueStatistics API](xref:titleid.playfabapi.com.multiplayer.matchmaking.getqueuestatistics). Servers always have access to all statistics. For more information, see [Displaying queue statistics in your title](display-statistics.md). -There are two options you can control within this: +There are two options you can control within this configuration: -1. **Show the number of players matching** - Whether the number of players waiting for a match is exposed to players. Titles may use this to hide the relative popularity of the mode, or to keep player counts hidden for business reasons. +1. **Show the number of players matching** - Whether the number of players waiting for a match is exposed to players. Titles may use this option to hide the relative popularity of the mode, or to keep player counts hidden for business reasons. 2. **Show the time to match statistics** - Whether the time to match statistics (average and percentiles) are exposed to players. ### Teams -A queue can include team configuration to have the match service assign players to teams. Additional team-specific rules can be used to control how team assignment is done. Furthermore, the match service will ensure that players matching together in the same ticket are not assigned to different teams. +A queue can include team configuration to have the match service assign players to teams. More team-specific rules can be used to control how team assignment is done. Furthermore, the match service ensures that players matching together in the same ticket aren't assigned to different teams. -You can have 2 or more teams defined in a queue. +You can have two or more teams defined in a queue. -+ **Team name** - The name used for this team. Team names are between 1 and 64 characters long (inclusive) and are case-sensitive. They are alphanumeric, plus underscores and hyphens, and start with a letter or number. In addition they must be unique within a queue. -+ **Team size** - Minimum and maximum number of players that can be on the team. Matchmaking will try to form teams with as many players as possible up to the maximum. ++ **Team name** - The name used for this team. Team names are between 1 and 64 characters long (inclusive) and are case-sensitive. They're alphanumeric, plus underscores and hyphens, and start with a letter or number. In addition, they must be unique within a queue. ++ **Team size** - Minimum and maximum number of players that can be on the team. Matchmaking tries to form teams with as many players as possible up to the maximum. -Besides defining the teams and their sizes, additional rules can be enabled to help with how to handle teams in matchmaking. See [below](#team-rule-types) for information on team-specific rules. +Besides defining the teams and their sizes, other rules can be enabled to help with how to handle teams in matchmaking. For information on team-specific rules, see [Team rule types](#team-rule-types). ## Rule configuration Rules may be optionally defined for a queue. When configured, they help the matchmaking algorithm determine which tickets should match together. Each rule applies to a single attribute in the player metadata. You can have a maximum of 20 rules defined for a single queue. -There are many types of rules. Each contains some common configurable elements, as well as elements that are specific to that particular type of rule. In addition, many rules allow an expansion, in which the rules become less restrictive over time. +There are many types of rules. Each contains some common configurable elements and elements that are specific to that particular type of rule. In addition, many rules allow an expansion, in which the rules become less restrictive over time. ### Common rule elements -The elements below are often used by all rules. +The following elements are often used by all rules. + **Rule Name** - The name must be between 1 and 255 characters long (inclusive), is alpha-numeric plus underscores and hyphens, and must start with a letter or number. Rule names must be unique within a queue. -+ **Weight** - A way to modify the importance of a rule. Rules in general provide both a restriction as well as a way to sort the remaining tickets that are eligible. The weight is a multiplier, modifying how important the rule is for sorting purposes. ++ **Weight** - A way to modify the importance of a rule. Rules in general provide both a restriction and a way to sort the remaining tickets that are eligible. The weight is a multiplier, modifying how important the rule is for sorting purposes. For more information, see [Understanding rule weight in matchmaking](rule-weights.md). + **Attribute Source** - Rules often act upon information that is provided to them. This field describes two options for the source of this information: 1. **User** - Attributes are submitted alongside players in the create or join ticket request. - 2. **Player Entity** - Attributes are retrieved from the player's associated Player Entity. These can be set via the [SetObjects API](xref:titleid.playfabapi.com.data.object.setobjects). DO NOT use this source when using external entity types. + 2. **Player Entity** - Attributes are retrieved from the player's associated Player Entity. You can set these attributes via the [SetObjects API](xref:titleid.playfabapi.com.data.object.setobjects). DO NOT use this source when using external entity types. + **Attribute Path** - The path to reach the attribute. When using a User Attribute Source, it is simply the name of the attribute. When using a Player Entity Attribute Source, it is a [JSONPath](https://github.com/json-path/JsonPath) that retrieves a particular item from the entity, such as `$.playerSkill.Mean`. + **Behavior when attribute is not specified** - If a rule requires an attribute, but none is specified, the rule may be configured with one of two behaviors: 1. It may supply a default value for the attribute. - 2. It may use this as a signal to indicate the ticket meets any restriction supplied by the rule. This may be useful if for instance, some players express a preference, and another player is willing to match anyone. The player with no preference can neglect to supply an attribute, and match with any other players. + 2. It may use this signal as a way to indicate the ticket meets any restriction supplied by the rule. This behavior may be useful if, for instance, some players express a preference, and another player is willing to match anyone. The player with no preference can neglect to supply an attribute, and match with any other players. ### Standard rule types -Each of the rule types is listed below, along with its purpose, some common uses, and any specific configuration the rule may require. +Each of the following rule types is listed along with its purpose, some common uses, and any specific configuration the rule may require. | Rule type | Description | Common Uses | Rule-specific fields | |-----------------|-------------|-------------|----------------------| | String Equality | Ensures that a string attribute is the same across all tickets in a match. | Requires build versions or other specific items to match | none | | Difference | Ensures that the absolute difference for a number attribute between any two tickets in a match is less than a configured maximum difference. | Groups players by skill, experience, or other numeric comparisons | Merge function - Select how multiple player values are merged into one value representing the ticket. Choices are min, max, and average. Defaults to average. | -| Set Intersection | Ensures that for a given attribute that is a list of strings, all tickets in a match share at least as many values as is configured. | DLC or map selection | Min intersection size - Minimum number of shared items for a match. | +| Set Intersection | Ensures that for a given attribute that is a list of strings, all tickets in a match share at least as many values as is configured. | Downloadable content (DLC) or map selection | Min intersection size - Minimum number of shared items for a match. | | Match Total | Ensures that the sum of a number attribute across all players in a match is within a configured range. | Role selection, emulating host/server matchmaking, adjusting player count restrictions over time | Min/Max total - Sum of attribute must be within these inclusive bounds. | | Region Selection | Ensures that the latency to a common data center for all users of the match is less than a configured max value. | Required for multiplayer server integration | Max Latency - Only datacenters within this max latency are eligible for a match. | ### Team rule types -Team rules can only be set if teams are present in the queue configuration. They provide additional ways to require balance between the teams. The following team rules are available: +Team rules can only be set if teams are present in the queue configuration. They provide more ways to require balance between the teams. The following team rules are available: | Rule type | Description | Common Uses | Rule-specific fields | |-----------------|-------------|-------------|----------------------| -| Team Difference | Ensures that teams included in a match are within a configured difference for a specific attribute (such as skills). This is very similar to a standard Difference Rule, except that the values compared are each team's average value. | Balancing skills across teams | none | -| Team Size Balance | Ensures the difference in player count between the largest and smallest team does not exceed a threshold. For instance, this rule could be used to create a queue where 3v3 and 4v4 matches are allowed, but a 3v4 is not. | Player count balance across teams | Allowed Team Size Difference - How uneven the teams can be, as measured by the difference in the number of players assigned to each one. | -| Team Ticket Size Similarity | Ensures that all teams either have a large party, or do not have a large party. A large party is defined as at least half of the maximum team's size. | Prevents parties (pre-made teams) from matching with a group of solo players. | none | +| Team Difference | Ensures that teams included in a match are within a configured difference for a specific attribute (such as skills). This is similar to a standard Difference Rule, except that the values compared are each team's average value. | Balancing skills across teams | none | +| Team Size Balance | Ensures the difference in player count between the largest and smallest team doesn't exceed a threshold. For instance, this rule could be used to create a queue where 3v3 and 4v4 matches are allowed, but a 3v4 isn't. | Player count balance across teams | Allowed Team Size Difference - How uneven the teams can be, as measured by the difference in the number of players assigned to each one. | +| Team Ticket Size Similarity | Ensures that all teams either have a large party, or don't have a large party. A large party is defined as at least half of the maximum team's size. | Prevents parties (premade teams) from matching with a group of solo players. | none | ### Expansions and becoming optional -Rules may become optional or less restrictive over time, allowing tickets that have waited for some time to search wider for a potential match. There are two methods for controlling this behavior: +Rules may become optional or less restrictive over time, allowing tickets that wait for some time to search wider for a potential match. There are two methods for controlling this behavior: -1. **Seconds until optional** - Simply indicates a length of time that the rule is active. The rule no longer restricts matches among tickets that have waited this time. +1. **Seconds until optional** - Simply indicates a length of time that the rule is active. The rule no longer restricts matches among tickets that wait this time. -2. **Expansion process** - Rules gradually adjust their configured thresholds over time. For instance, a Difference Rule may require matches within a particular maximum difference. As a ticket waits, the rule may expand the maximum difference, permitting expansion to a larger and larger range for the ticket, and allowing it to be matched even if perfect opponents are unavailable. +2. **Expansion process** - Rules gradually adjust their configured thresholds over time. For instance, a Difference Rule may require matches within a particular maximum difference. As a ticket waits, the rule may expand the maximum difference. This expansion permits a larger and larger range for the ticket. It allows the ticket to be matched even if perfect opponents are unavailable. Expansions can be either **linear** or **custom**. In a linear expansion, a value grows over time, using a fixed change after each time interval. The items customized in a linear expansion are: @@ -112,9 +112,9 @@ Expansions can be either **linear** or **custom**. In a linear expansion, a valu In a custom expansion, the rule can use an arbitrary value each time the rule changes its restrictions. The following fields are used: + **Seconds between expansions** - How long in between each instance of the rule changing its restrictions -+ **One or more custom fields** that modifies a rule during the expansion. Each field is semicolon delimited to represent a different value which is used in each expansion's interval. The word "null" may be used in place of a value to indicate the rule is not active during this interval. ++ **One or more custom fields** that modifies a rule during the expansion. Each field is semicolon delimited to represent a different value that is used in each expansion's interval. The word "null" may be used in place of a value to indicate the rule isn't active during this interval. -The exact field modified depends on the rule. The following chart describes which rules have which kinds of expansions, and what fields are modified by the expansion. +The exact field modified depends on the rule. The following chart describes which rules have which kinds of expansions, and what fields the expansion modifies. | Rule type | Linear Expansion Allowed? | Custom expansion allowed? | Attribute modified during expansion | |------------------|-------------|-------------|----------------------| @@ -127,4 +127,4 @@ The exact field modified depends on the rule. The following chart describes whic | Team Size Balance| yes | yes | Allowed difference in number of players per team | | Team Ticket Size Similarity | no | no | n/a | -For more details on configuration use cases and examples, see [Matchmaking scenario and configuration examples](config-examples.md). +For more information on configuration use cases and examples, see [Matchmaking scenario and configuration examples](config-examples.md). diff --git a/playfab-docs/multiplayer/matchmaking/matchmaking-partition.md b/playfab-docs/multiplayer/matchmaking/matchmaking-partition.md new file mode 100644 index 000000000..55fffe864 --- /dev/null +++ b/playfab-docs/multiplayer/matchmaking/matchmaking-partition.md @@ -0,0 +1,48 @@ +--- +title: Matchmaking scaling +author: keithrkline +description: Describes how matchmaking scales under load +ms.author: kkline +ms.date: 02/25/2026 +ms.topic: article +ms.service: azure-playfab +keywords: playfab, multiplayer, matchmaking, partition, scaling, performance +ms.localizationpriority: medium +--- + +# How matchmaking scales under load + +## Overview + +When a queue receives a high volume of tickets, the service automatically scales its processing to maintain low match latency. As load increases, tickets are grouped using your queue's configured rules so that similar tickets—tickets more likely to be compatible—are evaluated together. As load decreases, these groups consolidate, giving the service a larger pool of tickets to choose from and improving match quality. + +This scaling is transparent to players, but the rules you configure on a queue influence how effectively the service can distribute work. Understanding this process can help you design queue configurations that scale efficiently. + +## What makes a rule scale well + +When the service needs to distribute tickets across its processing capacity, it looks for rule attributes that naturally divide tickets into roughly equal groups. Rules with a wide range of distinct values work best—they give the service more options for balancing load evenly. + +If no rule provides a good distribution, the service falls back to a general-purpose distribution that balances load without relying on rule attributes. For example, this happens when most tickets share identical attribute values. + +### Rules that partition well + ++ **String equality rules with diverse values**—Rules like `GameMode` or `Region` that have multiple distinct values across your player population create natural partition boundaries. The service can cleanly divide tickets into groups that share the same value. ++ **Required rules**—Rules that remain enforced throughout matching (without an expansion) are preferred for partitioning because they represent hard constraints. Splitting on these rules ensures that partition boundaries align with your strongest match requirements. ++ **Higher-weighted rules**—Rules with a greater [weight](rule-weights.md) are prioritized for partitioning. This approach means the rules you consider most important for match quality are also the ones most likely to guide how tickets are distributed. ++ **Difference rules with a spread of values**—Numeric rules like skill rating work well when player values are distributed across a range, allowing the service to split tickets into groups with similar values. + +### Rules that are less effective for partitioning + ++ **Rules where most tickets share the same value**—If nearly all players submit the same attribute value for a rule, the service can't use that rule to create a meaningful split. ++ **Rules with heavy wildcard usage**—When a large proportion of tickets uses a wildcard (match-any) value for a rule, that rule becomes less useful for dividing tickets into distinct groups. ++ **Rules with expansions**—Rules that become optional over time are deprioritized for partitioning because they represent softer constraints that may not hold during a ticket's lifetime. + +## Design considerations + +When designing matchmaking queues for games that may experience high ticket volumes, keep the following considerations in mind: + ++ **Distribute attribute values**—Rules with diverse attribute values across your player population produce better partition splits. If most players share the same value for a rule, it doesn't help balance load across partitions. ++ **Weight important rules higher**—The [weight](rule-weights.md) of a rule affects both match sorting priority and partition splitting priority. Assigning higher weights to the rules most important for match quality ensures those rules also guide how tickets are distributed. ++ **Avoid unnecessary wildcards**—When a large proportion of tickets uses wildcard values for a rule, that rule becomes less useful for partitioning. Consider whether wildcard behavior is necessary for your game design. ++ **Retries during partition changes are normal**—When the partition layout changes due to a split or merge, some tickets may be briefly canceled with a retry signal. The matchmaking SDK handles this automatically, so players experience only a momentary delay. + diff --git a/playfab-docs/multiplayer/matchmaking/rule-weights.md b/playfab-docs/multiplayer/matchmaking/rule-weights.md new file mode 100644 index 000000000..0d327f8e4 --- /dev/null +++ b/playfab-docs/multiplayer/matchmaking/rule-weights.md @@ -0,0 +1,237 @@ +--- +title: Understanding rule weight in matchmaking +author: keithrkline +description: Explains how the Weight property on matchmaking rules affects match quality and ticket sorting +ms.author: kkline +ms.date: 02/24/2026 +ms.topic: conceptual +ms.service: azure-playfab +keywords: playfab, multiplayer, matchmaking, weight, rules, configuration +ms.localizationpriority: medium +--- + +# Understanding rule weight in matchmaking + +## Overview + +When you configure a matchmaking queue, you can assign each rule a **Weight** value. Weight is a numeric multiplier that controls how much influence a particular rule has when the matchmaking system ranks and sorts eligible tickets. It doesn't change whether a ticket passes or fails a rule—it only affects **how important that rule is relative to others** when determining which tickets are the best candidates for a match. + +Understanding weight is essential for tuning match quality. By adjusting weights across your rules, you can prioritize what matters most for your game—whether that's skill balance, geographic proximity, or shared content. + +## How weight works + +Every rule that supports weight computes a **distance** value for each pair of tickets being evaluated. This distance represents how similar or different two tickets are according to that rule: + +- A distance of **0** means the tickets are a perfect match for that rule. +- A distance closer to **1** means the tickets are at the edge of what the rule allows. +- A distance of **infinite** (hard rejection) means the tickets can't match according to that rule, regardless of weight. + +The matchmaking system calculates a **total distance** across all weighted rules using the following formula: + +``` +totalDistance = Σ (rule.Weight × rule.Distance) +``` + +Tickets with a lower total distance are considered better candidates and are tried first when building a match. Weight acts as a scalar multiplier on each rule's contribution to this total. + +> [!IMPORTANT] +> Weight does **not** override hard restrictions. If a rule determines that two tickets are incompatible, the tickets are excluded entirely. For example, this happens with a Difference Rule where the values exceed the maximum allowed difference. Weight only influences the **priority order** among tickets that are already eligible. + +## How each rule computes distance + +Before you look at weight examples, it helps to understand how each weighted rule computes its distance value. The distance is always a number between 0 and 1, where lower values indicate a closer match. + +| Rule type | Distance formula | Distance = 0 | Distance = 1 | +|-----------|-----------------|---------------|--------------| +| Difference | `absoluteDifference / maxDifference` | Player values are identical | Players differ by the full allowed amount | +| String Equality | 0 if strings match; 1 if the rule is optional and strings differ | Strings are identical | Rule is optional and strings differ | +| Set Intersection | `1 / (1 + sharedItemCount)` | N/A (minimum is 0.5 with one shared item) | No shared items (`1 / (1 + 0) = 1`) | +| Match Total | `(maxTotal - (groupTotal + ticketValue)) / maxTotal` | Group is at the target capacity | Group is far from the target total | +| Region Selection | `1 / (1 + Σ qualityTerms)` | Many low-latency common regions | Few or poor common regions | + +## Which rules support weight + +Weight applies to the **standard rule types** that participate in distance-based sorting. The following rules support the Weight property: + +| Rule type | Supports Weight | +|-----------|:-:| +| String Equality | ✔ | +| Difference | ✔ | +| Set Intersection | ✔ | +| Match Total | ✔ | +| Region Selection | ✔ | + +The following **team rule types** do **not** support weight. These rules act as validators—they either pass or fail a match and don't participate in distance-based sorting: + +| Rule type | Supports Weight | Behavior | +|-----------|:-:|-------------| +| Team Difference | ✘ | Validates that team averages are within an allowed difference | +| Team Size Balance | ✘ | Validates that team player counts are balanced | +| Team Ticket Size Similarity | ✘ | Validates that teams have similar party compositions | + +## Valid weight values + +Weight must be a number **greater than 0** and **up to 1000** (inclusive). A weight of 0 isn't permitted. If no weight is specified, the default value is **1**. + +## Examples + +The following examples use a queue with a **Difference Rule** for skill and a **Set Intersection Rule** for preferred game maps. Three players—Alice, Bob, and Charlie—are in the queue. The matchmaking system needs to decide which of the two candidates (Bob or Charlie) is the better match for Alice. + +### Queue configuration + +```json +"Rules": [ + { + "Type": "DifferenceRule", + "Name": "SkillRule", + "Attribute": { "Path": "skill", "Source": "User" }, + "MaxDifference": 10, + "MergeFunction": "Average", + "Weight": 1 + }, + { + "Type": "SetIntersectionRule", + "Name": "MapRule", + "Attribute": { "Path": "preferredMaps", "Source": "User" }, + "MinIntersectionSize": 1, + "Weight": 1 + } +] +``` + +### Player attributes + +| Player | Skill | Preferred Maps | +|--------|-------|----------------| +| Alice | 20 | "Dustbowl", "Summit", "Lakeside" | +| Bob | 24 | "Dustbowl," "Summit" | +| Charlie | 17 | "Lakeside" | + +### Step 1: Compute per-rule distances + +**SkillRule** (Difference Rule) uses the formula `absoluteDifference / maxDifference`: + +- Alice vs Bob: `|20 - 24| / 10 = 4 / 10 = 0.4` +- Alice vs Charlie: `|20 - 17| / 10 = 3 / 10 = 0.3` + +**MapRule** (Set Intersection Rule) uses the formula `1 / (1 + sharedItemCount)`: + +- Alice vs Bob: They share "Dustbowl" and "Summit" (two items) → `1 / (1 + 2) = 0.33` +- Alice vs Charlie: They share "Lakeside" (one item) → `1 / (1 + 1) = 0.5` + +### Example 1: Equal weights + +With both rules at Weight = 1, the total distance is: + +``` +Bob: totalDistance = (1 × 0.4) + (1 × 0.33) = 0.73 +Charlie: totalDistance = (1 × 0.3) + (1 × 0.5) = 0.80 +``` + +**Result:** Bob (0.73) is a better match than Charlie (0.80). Even though Charlie is closer in skill, Bob shares more maps with Alice, and both rules contribute equally. Bob is tried first. + +### Example 2: Prioritizing skill (Weight = 10 on SkillRule) + +If your game is competitive and skill balance matters most, increase the SkillRule weight: + +```json +{ + "Type": "DifferenceRule", + "Name": "SkillRule", + ... + "Weight": 10 +}, +{ + "Type": "SetIntersectionRule", + "Name": "MapRule", + ... + "Weight": 1 +} +``` + +Now the total distances change: + +``` +Bob: totalDistance = (10 × 0.4) + (1 × 0.33) = 4.33 +Charlie: totalDistance = (10 × 0.3) + (1 × 0.5) = 3.50 +``` + +**Result:** Charlie (3.50) is now the better match. The higher weight on skill means Charlie's closer skill level (three difference vs 4) outweighs the fact that Bob shares more maps. Skill dominates the sort order. + +### Example 3: Prioritizing shared maps (Weight = 10 on MapRule) + +If your game is casual and players care most about playing on their favorite maps, increase the MapRule weight instead: + +```json +{ + "Type": "DifferenceRule", + "Name": "SkillRule", + ... + "Weight": 1 +}, +{ + "Type": "SetIntersectionRule", + "Name": "MapRule", + ... + "Weight": 10 +} +``` + +Now the total distances become: + +``` +Bob: totalDistance = (1 × 0.4) + (10 × 0.33) = 3.70 +Charlie: totalDistance = (1 × 0.3) + (10 × 0.5) = 5.30 +``` + +**Result:** Bob (3.70) is preferred. Sharing two maps with Alice gives Bob a significant advantage, and the small skill gap with Charlie barely matters. Map preference dominates the sort order. + +### Example 4: When players can't match (hard rejection) + +Now add a fourth player, **Dave**, whose skill is far from Alice's and who shares no preferred maps: + +| Player | Skill | Preferred Maps | +|--------|-------|----------------| +| Alice | 20 | "Dustbowl," "Summit," "Lakeside" | +| Dave | 35 | "Fortress" | + +**SkillRule:** `|20 - 35| / 10 = 15 / 10 = 1.5`—but the difference of 15 exceeds `MaxDifference` (10), so the rule returns **infinite distance** (hard rejection). + +**MapRule:** Alice and Dave share 0 maps, and `MinIntersectionSize` is 1, so this rule also returns **infinite distance**. + +``` +Dave: totalDistance = infinite (skill difference 15 > MaxDifference 10 → hard rejection) +``` + +No matter how the weights are configured, Dave can't match with Alice. Even if only one rule returns infinite distance, the entire total distance becomes infinite and the ticket is excluded from the candidate list. Weight can't override a hard rejection—it can only influence priority among tickets that are already eligible. To allow players like Dave to eventually match, use [rule expansions](config-queues.md#expansions-and-becoming-optional) to relax the restrictions over time. + +### Summary of the examples + +The table below shows how weight changes which candidate is preferred, using the same player attributes and the same rules—only the weights differ. + +| Weight configuration | Bob's total distance | Charlie's total distance | Dave's total distance | Best match for Alice | +|---|:-:|:-:|:-:|---| +| Skill = 1, Maps = 1 (equal) | 0.73 | 0.80 | ∞ (rejected) | Bob | +| Skill = 10, Maps = 1 (skill priority) | 4.33 | 3.50 | ∞ (rejected) | Charlie | +| Skill = 1, Maps = 10 (map priority) | 3.70 | 5.30 | ∞ (rejected) | Bob | + +The underlying distances never change—only the relative importance assigned to each rule changes. Dave is always rejected because the player's attributes exceed the hard limits, regardless of weight. This approach is the power of weight tuning. + +## Weight and rule expansions + +When a rule becomes optional (through [Seconds until optional](config-queues.md#expansions-and-becoming-optional) or expansion), it no longer hard-rejects tickets. However, tickets that would be rejected still receive a nonzero distance value. Weight continues to scale this distance, which means optional rules still influence the sort order—they push "violating" tickets lower in priority rather than excluding them entirely. + +This behavior is useful for ensuring that even when rules relax over time, the best matches are still preferred. + +## Best practices + +- **Start with equal weights** and adjust based on match quality feedback from your players. +- **Use higher weights** on the rules that are most important to your game's experience (such as skill for competitive titles, or shared content for casual games). +- **Remember that weight only affects sorting**—it can't make an impossible match happen. Use [expansions](config-queues.md#expansions-and-becoming-optional) to relax hard restrictions over time. +- **Avoid extreme weight ratios** (such as 1000:1) unless you intentionally want one rule to completely overshadow all others. + +## See also + +- [Configuring matchmaking queues](config-queues.md) +- [Matchmaking scenario and configuration examples](config-examples.md) +- [Specifying attributes with your tickets](ticket-attributes.md) diff --git a/playfab-docs/multiplayer/matchmaking/toc.yml b/playfab-docs/multiplayer/matchmaking/toc.yml index 829c2740e..7c7697aa2 100644 --- a/playfab-docs/multiplayer/matchmaking/toc.yml +++ b/playfab-docs/multiplayer/matchmaking/toc.yml @@ -19,6 +19,10 @@ items: href: config-examples.md - name: Specifying attributes with your tickets href: ticket-attributes.md + - name: Understanding rule weight in matchmaking + href: rule-weights.md + - name: How matchmaking scales under load + href: matchmaking-partition.md - name: Using server backfill tickets - Multiplayer SDK href: backfill-tickets-multiplayer-sdk.md - name: Using server backfill tickets - REST API diff --git a/playfab-docs/multiplayer/servers/author-a-game-server-build.md b/playfab-docs/multiplayer/servers/author-a-game-server-build.md index 6829664b9..bdf1a26ef 100644 --- a/playfab-docs/multiplayer/servers/author-a-game-server-build.md +++ b/playfab-docs/multiplayer/servers/author-a-game-server-build.md @@ -36,10 +36,10 @@ This new build now helps manage game servers that are created using PlayFab Mult When using Windows game servers, you have to use the managed Windows container image. So the PlayFab Multiplayer Game Server Build can be uploaded as a zipped file combined with other dependencies (DLL files) during the [Deploy a build](deploying-playfab-multiplayer-server-builds.md) process. To help you determine what needs to be included in the zipped file, see [Determining required DLLs](determining-required-dlls.md). -When using Linux game servers, you need to [Create your custom Linux container image](deploying-linux-based-builds.md) and the PlayFab Multiplayer Game Server Build can be included as part of the image. Once your custom image is uploaded, you would be able to [Deploy a build](deploying-playfab-multiplayer-server-builds.md). +When using Linux game servers, you need to [Create and deploy Linux Builds](deploying-linux-based-builds.md) and the PlayFab Multiplayer Game Server Build can be included as part of the image. Once your custom image is uploaded, you would be able to [Deploy a build](deploying-playfab-multiplayer-server-builds.md). ## See also * [Determine DLL files to be included in the asset package for Windows servers](determining-required-dlls.md) * [Local debugging and integration for Windows servers](locally-debugging-game-servers-and-integration-with-playfab.md) -* [Create Linux servers](deploying-linux-based-builds.md) +* [Create and deploy Linux Builds](deploying-linux-based-builds.md) diff --git a/playfab-docs/multiplayer/servers/build-definition.md b/playfab-docs/multiplayer/servers/build-definition.md index 638a08a57..b26f0fe3a 100644 --- a/playfab-docs/multiplayer/servers/build-definition.md +++ b/playfab-docs/multiplayer/servers/build-definition.md @@ -34,7 +34,7 @@ For sample values you can use to deploy a simple server, see [Walk-through of de | Virtual machine (VM) selection | A drop-down list of global distributed Azure VMs with different technical specifications | Select the VMs based on what you need—number of cores, RAM, storage, region. For details, see [Multiplayer Servers details and price sheet](https://playfab.com/mps-detailed-pricing/). | | Servers per machine | Number of game servers hosted on each VM. The number of cores in the VM is split by the number of servers. | | | Virtual machine OS | Select Windows or Linux platform. | | -| Container | The container that will host your game server. | For Windows, you can simply select the managed Windows Server Core containers. For Linux-based VMs, see [Deploying Linux-based builds](deploying-linux-based-builds.md).| +| Container | The container that will host your game server. | For Windows, you can simply select the managed Windows Server Core containers. For Linux-based VMs, see [Create and deploy Linux Builds](deploying-linux-based-builds.md).| | Assets | Files you want uploaded on the servers. You can upload multiple assets but one of the assets **must** contain your [PlayFab Multiplayer Game Server Build](#).
All assets combined should be less than 10 GB in size and must be in *zip*, *tar.gz, or *tar* file type.
Each asset has a mount path associated with it. This specifies where it's mounted in the container file system.| Asset filenames can only contain alphanumeric characters, underscores, hyphens, and periods. You can use C:\Assets as the typical mount path. What this means that PlayFab will unzip your assets and mount it **in the container file-system** (not the VM) as a folder in the **C** drive under Assets. | | Start command | The command to run when the game server starts, make sure to include any arguments that you need. | | | Network | Define the port name, number, and protocol (TCP or UDP) to be used for incoming network traffic. Outgoing (or solicited) network flows don't need to be configured. For more networking information, see [Connecting clients to game servers](connecting-clients-to-game-servers.md).| | diff --git a/playfab-docs/multiplayer/servers/deploy-using-game-manager.md b/playfab-docs/multiplayer/servers/deploy-using-game-manager.md index 9b4d6ce4b..161edbafa 100644 --- a/playfab-docs/multiplayer/servers/deploy-using-game-manager.md +++ b/playfab-docs/multiplayer/servers/deploy-using-game-manager.md @@ -36,7 +36,7 @@ For details about the values you can use for each parameter, see [Build definiti 1. Next we have the server details portion where you'll need to select an OS type either **Windows** or **Linux**. Then you'll select your server type, either process or container based on the OS you choose. > [!Note] -> For Linux platform, you need to create your own container image. For more instructions, see [Create and deploy Linux container images](deploying-linux-based-builds.md). If you've already uploaded a container image, it will appear in the __Image__ dropdown. To use it, select the image. +> For Linux platform, you need to create your own container image. For more instructions, see [Create and deploy Linux Builds](deploying-linux-based-builds.md). If you've already uploaded a container image, it will appear in the __Image__ dropdown. To use it, select the image. Once you've selected your OS type, you can then choose the server type. Based on the OS/Server type you'll have the following features you can enable. diff --git a/playfab-docs/multiplayer/servers/deploy-using-powershell-api.md b/playfab-docs/multiplayer/servers/deploy-using-powershell-api.md index 5faaf21fe..d8ce0d5cd 100644 --- a/playfab-docs/multiplayer/servers/deploy-using-powershell-api.md +++ b/playfab-docs/multiplayer/servers/deploy-using-powershell-api.md @@ -84,7 +84,7 @@ If you receive an error that says `Title must have a valid payment instrument as Uploading an asset is mandatory when you're deploying a build for Windows servers. This is because your assets customize the managed Windows container image. -However, it's optional when deploying a build for Linux servers since you're able to customize the Linux container image. To learn more, see [Create Linux container images](deploying-linux-based-builds.md). +However, it's optional when deploying a build for Linux servers since you're able to customize the Linux container image. To learn more, see [Create and deploy Linux Builds](deploying-linux-based-builds.md). Run this command to upload an asset. @@ -101,7 +101,7 @@ For more details, see [New-PfAsset reference documentation](https://github.com/P ## Create a build * When creating a build for Windows servers, you need to have uploaded an asset. If not, see [Upload an asset](#upload-an-asset). -* When creating a build for Linux servers, you need to have uploaded your custom Linux container image to your PlayFab container registry. To learn more, see [Deploying Linux servers](deploying-linux-based-builds.md). +* When creating a build for Linux servers, you need to have uploaded your custom Linux container image to your PlayFab container registry. To learn more, see [Create and deploy Linux Builds](deploying-linux-based-builds.md). > [!IMPORTANT] > Make sure you use the correct values for __$vmSize__ and __$regions__ if you plan to take advantage of resources offered for [free evaluation](billing-for-thunderhead.md). diff --git a/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md b/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md index 4f478179a..249f54abe 100644 --- a/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md +++ b/playfab-docs/multiplayer/servers/deploying-linux-based-builds.md @@ -1,20 +1,24 @@ --- -title: Create and deploy Linux container images +title: Create and deploy Linux Builds author: joannaleecy -description: Create and deploy Linux container images. +description: Create and deploy Linux Builds. ms.author: jenelleb -ms.date: 04/01/2021 +ms.date: 03/19/2026 ms.topic: article ms.service: azure-playfab keywords: playfab, multiplayer servers, thunderhead, linux ms.localizationpriority: medium --- -# Create and deploy Linux container images +# Create and deploy Linux Builds -This article outlines specific steps to help you create and deploy Linux container images. +This article contains details on how to create Linux Builds on PlayFab Multiplayer Servers, both using containers and using processes. -As described in [Create VMs](deploying-playfab-multiplayer-server-builds.md), you configure VMs to be automatically spun up as game servers globally according to your budget and demand when using our service. In order to do so, you don't explicitly create VMs but define parameters that determine how they get created on your behalf. This process is called deploying or creating a build. +## Create and deploy Linux container images + +This section outlines specific steps to help you create and deploy Linux container images. + +As described in [Create virtual machines (VMs)](deploying-playfab-multiplayer-server-builds.md), you configure VMs to be automatically spun up as game servers globally according to your budget and demand when using our service. In order to do so, you don't explicitly create VMs but define parameters that determine how they get created on your behalf. This process is called deploying or creating a build. PlayFab Multiplayer Servers can deploy both Linux-based and Windows-based game servers. The way builds are deployed for Linux containers are similar to Windows containers with a few important differences. To learn more, see [Windows and Linux container image differences](#windows-and-linux-container-image-differences). If you want to use PowerShell/API to manage Linux containers, see [Manage Linux container images using APIs](#manage-linux-container-images-using-apis). @@ -30,8 +34,8 @@ This step is needed only if you want to use Windows development device to create [Windows Subsystem for Linux (WSL)](/windows/wsl/) enables you to use your development device in the familiar Windows environment to author and manage Linux container images. Using WSL means that you wouldn't need an overhead of a traditional Linux virtual machine or dual-boot setup. -1. [Install WSL 2](/windows/wsl/). Make sure that you've restarted your machine and are using WSL 2. You also need to have successfully installed the Linux kernel update package. -2. [Install a Linux distribution that uses WSL](/windows/wsl/install#step-6---install-your-linux-distribution-of-choice). Although our VMs use Ubuntu, you can select any distribution you want for your container image. Consider using [Ubuntu 20.04 LTS](https://www.microsoft.com/store/apps/9n6svws3rx71) or later versions. +1. [Install WSL 2](/windows/wsl/). Make sure that you restart your machine and are using WSL 2. You also need to install the Linux kernel update package. +2. [Install a Linux distribution that uses WSL](/windows/wsl/install#step-6---install-your-linux-distribution-of-choice). Although our VMs use Ubuntu, you can select any distribution you want for your container image. Consider using [Ubuntu 20.04 Long-Term Support (LTS)](https://www.microsoft.com/store/apps/9n6svws3rx71) or later versions. 3. [Install Docker Desktop for Windows with WSL 2](/windows/wsl/tutorials/wsl-containers). For direct download link, go to [Docker Desktop for Windows (external)](https://hub.docker.com/editions/community/docker-ce-desktop-windows/). **Verify WSL 2 set up** @@ -51,7 +55,7 @@ This step is needed only if you want to use Windows development device to create The Azure container registry account is associated with your PlayFab account. Only you have access to the containers uploaded there. This Azure container registry is free of charge. -* In Game Manager, select your game title, then __Multiplayer__ > __Servers__. Next, select __New build__ on the right to open the build creation page. +* In Game Manager, select your game title, then __Multiplayer__ > __Servers__. Select __New build__ to open the build creation page. * Select __Linux__ as the virtual machine operating system. * Take note of the sign-in credentials—name, password, and customer5555555.azurecr.io, as this information is needed later @@ -65,7 +69,7 @@ These steps help you create and push your custom Linux container image. #### Integrate your game server application with GSDK -Similar to using Windows servers, you have to integrate your game server code with the PlayFab Multiplayer Server SDK (GSDK). This can be part of your container image. +Similar to using Windows servers, you have to integrate your game server code with the PlayFab Multiplayer Server SDK (GSDK). The GSDK integration can be part of your container image. For instructions, see [Author a game server build](author-a-game-server-build.md) and [Integrating your title with PlayFab Game Server SDK (GSDK)](integrating-game-servers-with-gsdk.md). @@ -87,7 +91,7 @@ A Dockerfile is a text file with no extension and contains all commands needed t #### Build and upload Linux container image -1. Open your Linux terminal, making sure that you have installed Docker. +1. Open your Linux terminal with Docker installed. 2. Run the following Docker commands using the sign-in credentials obtained from the earlier step. Then follow the instructions on screen to enter your username and password. ```docker @@ -101,11 +105,11 @@ password: HRDFOdIebJkvBAS+usa55555555 ``` 3. Build the container image -Run the command below to build the container image using the Dockerfile in the folder/directory you are in. Note that there's a "." at the end of __docker build__ command. +Run the following command to build the container image using the Dockerfile in your current directory. There's a "." at the end of the __docker build__ command. -The __-t__ flag specifies the name:tag information for your new container image. They'll be used if the build succeeds. If there are build errors, you have to fix them before moving on to the next step. +The __-t__ flag specifies the name:tag information for your new container image. The name and tag are used if the build succeeds. If there are build errors, you have to fix them before moving on to the next step. -In the example below, the repository name is __customer5555555.azurecr.io/pvp_gameserver__ and tag is __v1__. For more information, see [docker build command reference (external link)](https://docs.docker.com/engine/reference/commandline/build/) and [Building Dockerfile (external link)](https://docs.docker.com/engine/reference/builder/). +In the following example, the repository name is __customer5555555.azurecr.io/pvp_gameserver__ and tag is __v1__. For more information, see [docker build command reference (external link)](https://docs.docker.com/engine/reference/commandline/build/) and [Building Dockerfile (external link)](https://docs.docker.com/engine/reference/builder/). When using WSL, the Windows C: drive is mounted at /mnt/c. * Then run __cd /mnt/c/path/to/your/Dockerfile__ to switch to the path where your Dockerfile is. @@ -120,7 +124,7 @@ docker build -t customer5555555.azurecr.io/pvp_gameserver:v1 . 4. Upload the container image -Run the below commands to push the image to your PlayFab Container registry. Select a meaningful and helpful name:tag combination for your uploaded container image. Then use [docker push](https://docs.docker.com/engine/reference/commandline/push/) or another container registry client, to upload your container to the PlayFab operated registry. +Run the commands to push the image to your PlayFab Container registry. Select a meaningful and helpful name:tag combination for your uploaded container image. To upload your container to the PlayFab operated registry, use [docker push](https://docs.docker.com/engine/reference/commandline/push/) or another container registry client. ```docker docker tag hello-world customer5555555.azurecr.io/pvp_gameserver:v1 @@ -140,12 +144,12 @@ For many developers, using Windows managed container is the preferred simple and > [!Note] > You are able to fully customize your game servers whether you are using Windows or Linux container images. When using Windows servers, you customize the managed container image by uploading assets. -The table below lists some differences when creating and using them. +The following table lists some differences when creating and using them. | Developer options| Windows | Linux | |------------------|-------------------------|---------------| | Development device OS | Windows OS | [Windows Subsystem for Linux (WSL)](#set-up-your-windows-development-device) or Linux OS (using dual-OS or VMs)| -| Container image | Straightforward deployment using our managed container image. You can still customize the container by uploading additional files as assets. | Additional work is needed because you have to create your own custom container image that gives you complete control. | +| Container image | Straightforward deployment using our managed container image. You can still customize the container by uploading extra files as assets. | More work is needed because you have to create your own custom container image that gives you complete control. | ## Manage Linux container images using APIs @@ -154,14 +158,77 @@ You can use APIs to manage Linux container images. For the rest of build lifecyc * [GetContainerRegistryCredentials](/rest/api/playfab/multiplayer/multiplayer-server/get-container-registry-credentials): Retrieve a container registry address, user name, and password * [ListContainerImages](/rest/api/playfab/multiplayer/multiplayer-server/list-container-images) and [ListContainerImageTags](/rest/api/playfab/multiplayer/multiplayer-server/list-container-image-tags): Ensure your new image and tag are listed (sometimes it might take a couple of minutes for image to be fully registered in the system) * [CreateBuildWithCustomContainer](/rest/api/playfab/multiplayer/multiplayer-server/create-build-with-custom-container): Create a build with a custom container. Specify the tagged image you uploaded earlier. Ensure the following properties are set on the request: - * **ContainerImageReference** - The image name and tag that was uploaded earlier (and is visible in ListContainerImages and ListContainerImageTags above). + * **ContainerImageReference** - The image name and tag that was uploaded earlier. These values are visible in ListContainerImages and ListContainerImageTags. * **ContainerFlavor** - "CustomLinux" - * **ContainerRunCommand** (Optional) - In case your container doesn't have a default command that it runs, this can be used to provide the command to run, along with any arguments. + * **ContainerRunCommand** (Optional) - If your container doesn't have a default command, use this property to provide the command to run, along with any arguments. + +## Packaging assets for Linux process-based servers + +When using Linux in **process mode** (instead of container mode), you upload your game server as an asset archive rather than a container image. This section covers important packaging requirements. + +### Supported archive formats + +Assets should be uploaded as `.tar.gz`, or `.tar` files, so Unix file permissions (such as the execute bit) can be preserved during extraction. + +> [!WARNING] +> **`.zip` files do not preserve Unix file permissions on Linux.** If you upload your Linux game server executable in a `.zip` archive, it loses its execute permission and fails to start with a "Permission denied" error. To work around this issue, either use `.tar.gz` instead, or set your start command to a shell script that runs `chmod +x` on your executable before launching it. + +### Tar.gz and tar archive structure requirements + +When extracting `.tar` or `.tar.gz` archives, PlayFab Multiplayer Servers strips the first directory level from the archive (equivalent to `tar --strip-components=1`). Your archive **must** contain a single top-level wrapper directory with all your game files inside it. + +**Proper structure** — files inside a top-level directory: + +``` +MyGameServer/ +├── MyGame.x86_64 +├── MyGame_Data/ +│ └── ... +├── UnityPlayer.so +└── start_server.sh +``` + +Create the archive with: + +```bash +tar czf MyGameServer.tar.gz MyGameServer/ +``` + +> [!CAUTION] +> If your files are at the root of the archive without a wrapper directory, they are **silently skipped** during extraction. Your game server fails with "No such file or directory" errors because the executable is never written to disk. + +### Setting the start command + +For process-based servers, the start command should be **relative to the root asset folder after extraction** (that is, relative to where files end up after the top-level directory is stripped). + +For example, if your archive contains `MyGameServer/MyGame.x86_64`, after extraction the file is at the root of the asset folder. Set your start command to: + +``` +MyGame.x86_64 +``` + +If your executable is inside a subfolder (for example, `MyGameServer/bin/MyGame.x86_64`), set the start command to: + +``` +bin/MyGame.x86_64 +``` + +## Manage Linux process-based builds using APIs + +You can use APIs to manage Linux process-based builds. For the rest of build lifecycle (viewing usage, updating regions and standingBy configurations, deletion), manage them using Game Manager. + +* [CreateBuildWithProcessBasedServer](/rest/api/playfab/multiplayer/multiplayer-server/create-build-with-process-based-server): Create a build with the game server running as a process. Ensure the following properties are set on the request: + * **OsPlatform** - "Linux" + * **GameAssetReferences** - The list of game assets (uploaded as `.tar.gz` or `.tar` files). Each asset requires a **FileName** matching the uploaded asset name. + * **StartMultiplayerServerCommand** - The command to run when the game server starts. The path should be relative to the root asset folder after extraction (for example, `MyGame.x86_64 -server`). + * **Ports** - The ports to map for the build. + * **MultiplayerServerCountPerVm** - The number of game server instances to host on a single VM. + * **RegionConfigurations** - The regions to deploy to, with standby and maximum server counts. ## See also * [Intro to docker containers](/training/modules/intro-to-docker-containers/) * [Create your first server](create-your-first-server.md) * [Resources and samples](server-samples-resources.md) -* [PlayFab Multiplayer Server SDKs](server-sdks.md) +* [PlayFab Multiplayer Server Software Development Kits (SDKs)](server-sdks.md) * [API Reference](xref:titleid.playfabapi.com.multiplayer.multiplayerserver) diff --git a/playfab-docs/multiplayer/servers/toc.yml b/playfab-docs/multiplayer/servers/toc.yml index e492edf73..089c091a5 100644 --- a/playfab-docs/multiplayer/servers/toc.yml +++ b/playfab-docs/multiplayer/servers/toc.yml @@ -36,7 +36,7 @@ href: deploy-using-game-manager.md - name: Deploy builds using PowerShell/API href: deploy-using-powershell-api.md - - name: Create Linux container images + - name: Create and deploy Linux Builds href: deploying-linux-based-builds.md - name: Server build lifecycle href: multiplayer-build-lifecycle.md From 39dab8eb73dcc22737b94e93fef617ba1db30587 Mon Sep 17 00:00:00 2001 From: "learn-build-service-prod[bot]" <113403604+learn-build-service-prod[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 13:22:20 -0700 Subject: [PATCH 74/76] =?UTF-8?q?Auto=20Publish=20=E2=80=93=20main=20to=20?= =?UTF-8?q?live=20-=202026-03-31=2017:00=20UTC=20(#2885)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initialize Docs repository: https://github.com/MicrosoftDocs/playfab-docs-pr of branch main * [PubSub] Rename "Notifications" to "Messages" in PubSub docs. Also add a note for PubSub clients about ensuring they set KeepAliveInterval (#2843) * [PubSub] Rename "Notifications" to "Messages" in PubSub docs. Also add a note for PubSub clients about ensuring they set KeepAliveInterval * Fix Acrolinx grammar issues to meet minimum 80 score - Fix possessive 'it's' -> 'its' in mpintro.md - Replace 'aka' with 'also known as' in mpintro.md - Replace 'e.g.' with 'for example' in mpintro.md - Fix 'ex:' -> 'for example' and missing 'be' in signalr-hub.md - Expand 'you're' -> 'you are' in signalr-hub.md - Fix double space and contractions in start-or-recover-session-response.md - Replace 'don't' with 'do not' across all 18 PubSub NOTE blocks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * retrigger checks * retrigger Acrolinx checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * acrolinx updates * acrolinx clarity --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update (#2841) Co-authored-by: OpenPublishing.Build * PlayStream Event Documentation Updates: Experimentation, PlayStream (actions), Segmentation, TargetedConfiguration (player churn) (#2826) * Add Experimentation events * Add Segmentation events * Add PlayStream actions events * Add player churn event * Fix typo in index.md * Fix some typos in index.md * move player-action-executed back to Player folder * Update table of contents with new event docs in this PR. * Game Saves linking doc (#2761) * Initial draft of linking doc * MS learn requirements * Fixing invalid apostrophe characters * Fixing a few header levels * Added suggested changes to sample code * Misc fixes * Fix correctness issues and Acrolinx style in linking.md - Replace XAsyncGetStatus with PFAuthenticationLoginWithXUserGetResultSize in Strategy 2 sample (XAsyncGetStatus doesn't return PF error codes) - Add note about RETURN_IF_FAILED in void XAsyncBlock callbacks - Fix typo: defered -> deferred - Acrolinx: login -> sign-in for user actions, add contractions, remove filler words, fix future tense, expand MSA acronym - Convert blockquote to [!TIP] callout for player-facing wording note - Add [!IMPORTANT] callout warning about static XAsyncBlock lifetime - Add caller-responsibility comments for heap-allocated context structs - Add See also section with links to related docs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refactor Strategy 2 sample code and add flow diagram - Extract helper functions: RunReconciliation, BeginLateLink, BootstrapViaXbox, CheckLinkStatusAndPrompt - Reduce max nesting from 7 levels to 4; RunStrategy2Flow drops from ~140 lines to ~55 lines - Add forward declarations and banner comments for each helper - Add Mermaid flowchart showing the complete Strategy 2 decision tree between the prose walkthrough and the sample code Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Mermaid diagram syntax for Learn and VSCode rendering Remove HTML br tags, Unicode special characters, and parentheses from Mermaid node/edge labels that prevented rendering. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Replace Mermaid code block with rendered SVG diagram Learn doesn't support Mermaid natively, so render the Strategy 2 flow diagram as an SVG image. The .mmd source is kept alongside the SVG in media/ for future regeneration via mmdc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove Strategy 2 sample code and polish flow diagram - Remove the ~330-line Strategy 2 C++ sample. The prose walkthrough and flow diagram provide sufficient guidance; a full working sample should be added separately. - Restyle the SVG diagram with a custom Learn-friendly theme (soft blue nodes, Segoe UI font) and add horizontal padding to edge labels. - Add mermaid-learn.json config for future diagram regeneration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix diagram description: single terminal node, not multiple Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Minor Acrolinx fixes in Strategy 1 prose - Add missing comma after introductory clause - 'will require' -> 'requires', 'can just go' -> 'can go' (present tense) - 'different than' -> 'different from' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add verification callout for cross-platform link on returning players When a title requires the cross-platform identity to match the currently signed-in user, a successful platform login alone isn't sufficient. Added a NOTE callout after the happy path advising titles to verify the link via GetAccountInfo. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix forceLink guidance to distinguish AccountAlreadyLinked vs LinkedAccountAlreadyClaimed forceLink only resolves LinkedAccountAlreadyClaimed (platform account claimed by another entity). It does not resolve AccountAlreadyLinked (entity already has a different platform account linked). The latter requires an explicit Unlink call before re-linking. Updated prose, sample code comments, and mermaid diagram to reflect the correct two-error handling. Also fixed SVG background to transparent for dark mode support. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review feedback: style and terminology fixes - Convert all headings from title case to sentence case (DocuMentor rule) - Replace 'e.g.' with 'for example,' (8 instances) - Hyphenate 'first-party' and 'free-to-play' as compound adjectives - Fix 'OpenId Connect' to 'OpenID Connect' - Add backticks around LoginWithXbox and LoginWithOpenIdConnect - Use contraction 'wasn''t' instead of 'was not' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix sample code and error names verified against PlayFab.C source Verified linking.md claims against PlayFab.C SDK headers using the AGENTS.md bootstrap context added to PlayFab.C. Four issues found and fixed: 1. PFAccountManagementClientLinkSteamAccountGetResult does not exist - LinkSteamAccount is a void async op. Replaced with XAsyncGetStatus. 2. forceLink field is bool const* (optional pointer), not bool. The previous code set the pointer to null via 'false', which accidentally worked but would crash if set to 'true'. Replaced with commented-out pointer pattern showing correct usage. 3. Added ticketIsServiceSpecific field (required when using GetAuthTicketForWebApi with AzurePlayFab identity string). 4. Replaced service-side error string names (LinkedAccountAlreadyClaimed, AccountAlreadyLinked) with SDK HRESULT constants (E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED, E_PF_ACCOUNT_ALREADY_LINKED) throughout prose, tables, and code comments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jason Sandlin * Update Playfab release notes for 260313 (#2854) * Update Playfab release notes for 260313 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --------- Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Kkline matchupdates (#2847) * Add files via upload * Add section on rule weight in matchmaking * Update Weight description in config-queues.md Added a reference to 'Understanding rule weight in matchmaking' for clarity. * Add files via upload * Add matchmaking dynamic partitioning to TOC * Revise matchmaking dynamic partitioning documentation Revised version that includes less internal specifics. * Add section for lobby lifetime and expiration * Add files via upload * Fix typo in lobby and matchmaking documentation * Fix grammatical error in lobby ownership description Corrected grammatical error in the description of lobby ownership categories. * Clarify filter operators in find-lobbies.md * Revise matchmaking partitioning to include scaling details Changed some of the text to remove internal service specifics * Rename 'Matchmaking dynamic partitioning' to 'How matchmaking scales under load' * TEST AI acrolinx fixes (#2858) * acrolinx fixes * revert 'dust bowl' to 'dustbowl' revert 'dust bowl' to 'dustbowl' --------- Co-authored-by: edigonzales-microsoft * Add documentation for toxmod (#2848) * Add documentation for toxmod * resolve comments --------- Co-authored-by: edigonzales-microsoft * Add Linux process-based server asset packaging docs (#2861) * Add Linux process-based server asset packaging docs - Broaden page title from 'Linux container images' to 'Linux Builds' - Add new section: Packaging assets for Linux process-based servers - Document tar.gz top-level wrapper directory requirement - Document that zip does not preserve Unix file permissions - Add correct/incorrect archive structure examples - Add start command guidance for process mode - Add quick reference table (zip vs tar.gz) - Add Linux VM base image info (Ubuntu 22.04) and pre-installed libraries - Add warning about symlinks/hard links being silently skipped - Add Linux process mode limitations (crash dumps, process isolation) - Update toc.yml nav entry to match new title - Update cross-references in 4 other pages to use new title Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Acrolinx clarity issues in deploying-linux-based-builds.md - Replace present perfect tense with present tense - Expand acronyms on first use (VMs, LTS, SDKs) - Remove directional terms (below, above, on the right) - Use nouns after demonstrative pronouns (this, that) - Simplify word choices (additional -> other/extra/more) - Split complex sentences for readability - Remove filler phrases - Reword goal-before-action for docker push instruction Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fixes --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove toxmod-related notes (#2864) * I believe this fixes some compile errors in the c# example for entity… (#2801) * I believe this fixes some compile errors in the c# example for entity-files. * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestion from @rickcarr044 Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --------- Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Co-authored-by: Anthony Nguyen <108492711+antnguyen89@users.noreply.github.com> Co-authored-by: edigonzales-microsoft * ADO 61124898 - article revision (data-connection 'overview' and 'quickstart') (#2833) * ADO 61124898 - article revision (data-connection 'overview' and 'quickstart') * Update per Rachel's feedback and minor punctuation fixes. * PR 2833 requested changes and build update * Added references to AWS S3 in overview + quickstart for Data Connections --------- Co-authored-by: v-foxval@microsoft.com Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Co-authored-by: Rachel Akisada <87677950+raakisad@users.noreply.github.com> * PR #2846 review edits for amccalib/GameSaveTelemetry (#2873) * Add Game Saves PlayStream events telemetry doc - New playstream-events.md covering gamesave_version_finalized and gamesave_version_marked_known_good events with scenario guides - Cross-link from overview.md benefits and conflicts.md best practices - Add PlayStream Events entry to game-saves toc.yml Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * pf-game-save-telemetry-edits-03-24-2026-01 --------- Co-authored-by: amccalib Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jason Sandlin * add Playfab MLP v1.8.8 release notes (#2867) * Update screenshots in Release Notes section (#2863) * Add updated release-notes screenshots for review Added 1 updated Game Manager screenshot (-updated suffix). Ready for review. Use '/screenshot-pr accept' to overwrite original. Files added: - release-notes/images/171026-DelTitleGameManager-updated.png Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Accept screenshot: 171026-DelTitleGameManager.png Overwrote original with reviewed -updated version. Original: release-notes/images/171026-DelTitleGameManager.png Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * GetSegmentPlayerCount (preview) Tutorial w/ image (#2878) * player count (preview) tutorial with image) * suggested updates from checks * updated image name to comply with learn bot * nit removed Step 1 and added period to last sentence * Setting up the PlayFab doc repo for agentic workflows (#2866) * Add Copilot agent context files for PlayFab docs * Add agent and more * Add github action to automatically validate content * Integreate feedback from Scott Munro, Copilot, and others * Update .github/workflows/validate-docs.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix TOC validation: handle site-absolute hrefs and cross-platform path separators Agent-Logs-Url: https://github.com/MicrosoftDocs/playfab-docs-pr/sessions/841ef58d-f83a-4097-a172-cf639d7b5b85 Co-authored-by: JerGup <158191758+JerGup@users.noreply.github.com> * Fail fast in CI when git diff change detection fails Agent-Logs-Url: https://github.com/MicrosoftDocs/playfab-docs-pr/sessions/25480ea5-a358-4227-8556-d1c9d2036318 Co-authored-by: JerGup <158191758+JerGup@users.noreply.github.com> * Address remaining PR feedback: remove unused variable, fix TOC instructions - Remove unused $content = Get-Content -Raw in validate-docs.ps1 (file was being read redundantly; Get-Frontmatter and $lines already read it) - Update toc-files.instructions.md to mention site-absolute paths (/playfab-docs/...) as valid in addition to relative paths Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR feedback: LASTEXITCODE check, date/description validation, TOC path normalization - Add LASTEXITCODE check after local git diff to error out instead of silently passing - Add ms.date MM/DD/YYYY format validation and description 160-char limit check - Normalize backslashes in TOC href values for cross-platform compatibility Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR feedback: strip TOC inline comments, short-circuit on bad frontmatter - Strip inline YAML comments from TOC href values before validation to prevent false BROKEN_TOC_LINK errors - Short-circuit body checks (HTML, headings, alt-text) when frontmatter is missing or malformed to avoid noisy follow-on false positives Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Improve validate-docs.ps1: reduce false positives, add checks, boost perf Robustness (false-positive fixes): - Allow
tags in RAW_HTML detection (345 false positives eliminated) - Add quickstart and tutorial to valid ms.topic values (-29 false positives) - Accept single-digit month/day in ms.date format (-36 false positives) - Skip cross-repo absolute paths in TOC link validation Validity (new checks): - Validate relative markdown links in body (BROKEN_INTERNAL_LINK) - Validate [!INCLUDE references resolve to existing files (BROKEN_INCLUDE) - Strip fragment identifiers from TOC href before file-exists check - Trim whitespace from link targets for accurate path resolution Performance: - Replace O(n^2) array concatenation with List[object].Add() - Read each file once and reuse content (was reading twice per file) - Merge 4 separate body-scanning loops into single pass Result: 641 -> 266 issues (59% reduction, all remaining are genuine) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Incorporate acrolinx (style) information into the doc review agent, following suggestion from Andy McCalib. * Improve validate-docs.ps1 reliability, accuracy, and performance Reliability: - Skip writing-style checks inside inline code spans and blockquotes - Replace Set-Location with Push-Location/Pop-Location in try/finally - Add try/catch around file reads for graceful error handling - Robust code fence toggle: track fence char/length, support tildes and 4+ backticks Accuracy (new checks): - BROKEN_IMAGE: verify image file paths resolve to existing files - H1_TITLE_MISMATCH: warn when H1 heading diverges from frontmatter title - BARE_CODE_BLOCK: warn on code blocks without language specifiers - INVALID_DATE: reject impossible calendar dates via TryParseExact - ORPHANED_REDIRECT: flag .md files still on disk but listed in redirection JSON - Downgrade TOO_LONG from error to warning for machine-generated api-references Performance (42s -> 25s, -41%): - Pre-compile 16 regex patterns as [regex]::new(..., 'Compiled') - Cache Test-Path results in hashtable to deduplicate filesystem calls - Single Get-Content call per file instead of reading raw + splitting Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Jeremy Gup Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * release notes legacy sdk 260327 (#2883) * Update event configuration documentation for clarity and accuracy (#2884) * Update event configuration documentation for clarity and accuracy * Update metadata and fix documentation links Updated service name and topic in metadata, and fixed link to PlayStream events documentation. --------- Co-authored-by: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> * Fix case on png (#2852) * Fix case on png * Delete playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/Xbox-live-add-on-page.png * Delete playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/xbox-live-add-on-page.htm * Add files via upload * PFMultiplayer 1.9.0 and PFParty 1.10.18 (#2869) * PFMultiplayer 1.9.0 update * Include release notes * Apply Acrolinx suggestions * More Acrolinx suggestions * Add statement to clarify to initialize new field in structs * Remove 'the' * Fix typo --------- Co-authored-by: Berni Mora Escobar * Update Foundation Mode docs on pricing (#2859) * Update Foundation Mode docs: add missing features, billing section, and TOC entries - Add Developer Identity, Add-ons, Functions, PlayStream, and Reports to the What's included tables in mode-overview.md - Add new Billing and pricing section clarifying no-cost scope, per-title applicability, and relationship to existing plans - Clarify that Azure Functions invocations are included but compute (GB-s) is billed separately - Note that non-included features are blocked at the API level (no surprise bills) - Add foundation-onboarding and mode-overview to get-started/toc.yml Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * pf-gdc-docs-edits-03-25-2026-01 (#2876) --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> --------- Co-authored-by: v-alje <4665434+v-alje@users.noreply.github.com> Co-authored-by: Warren Alpert <1860902+WarrenAlpert@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: learn-build-service-prod[bot] <113403604+learn-build-service-prod[bot]@users.noreply.github.com> Co-authored-by: OpenPublishing.Build Co-authored-by: Joel Kucera Co-authored-by: Andy McCalib Co-authored-by: Jason Sandlin Co-authored-by: Steven Rojas Lizano Co-authored-by: Rick Carr <39857706+rickcarr044@users.noreply.github.com> Co-authored-by: Keith Kline <43284035+keithrkline@users.noreply.github.com> Co-authored-by: edigonzales-microsoft Co-authored-by: yuehanlin <99760142+yuehanlin@users.noreply.github.com> Co-authored-by: Dimitris-Ilias Gkanatsios Co-authored-by: Ronald Harding Co-authored-by: Anthony Nguyen <108492711+antnguyen89@users.noreply.github.com> Co-authored-by: Fox Valorguard <218149361+foxvalo@users.noreply.github.com> Co-authored-by: v-foxval@microsoft.com Co-authored-by: Rachel Akisada <87677950+raakisad@users.noreply.github.com> Co-authored-by: csuarezsandi Co-authored-by: Yessenia Garcia <103969751+yegarci@users.noreply.github.com> Co-authored-by: Jeremy Gup <158191758+JerGup@users.noreply.github.com> Co-authored-by: Jeremy Gup Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: anaisnlawson Co-authored-by: Kirsten Dearnley <91142640+m-kdearnley@users.noreply.github.com> Co-authored-by: Yuri Simernitski Co-authored-by: Berni Mora <93845766+BerniME@users.noreply.github.com> Co-authored-by: Berni Mora Escobar --- .github/PULL_REQUEST_TEMPLATE.md | 23 + .github/agents/docs-reviewer.md | 248 ++++++++ .github/copilot-instructions.md | 185 ++++++ .../api-references.instructions.md | 75 +++ .../release-notes.instructions.md | 65 ++ .../instructions/toc-files.instructions.md | 28 + .github/workflows/validate-docs.yml | 27 + CONTRIBUTING.md | 126 ++++ .../media/get-segment-player-count.png | Bin 0 -> 20852 bytes .../ingest-data/opt-in-events.md | 76 ++- playfab-docs/get-started/mode-overview.md | 26 +- playfab-docs/get-started/toc.yml | 5 + ...-on-page.png => xbox-live-add-on-page.png} | Bin .../segmentation/segmentation-player-count.md | 26 + .../lobby-and-matchmaking-release-notes.md | 21 + .../pflobbygetrestrictinvitestolobbyowner.md | 53 ++ .../pflobby/pflobby_members.md | 3 +- .../pflobbyarrangedjoinconfiguration.md | 9 +- .../structs/pflobbycreateconfiguration.md | 15 +- .../pflobby/structs/pflobbydataupdate.md | 22 +- .../structs/pflobbyupdatedstatechange.md | 7 +- .../playfabmultiplayerreference-cpp/toc.yml | 2 + .../multiplayer/networking/release-notes.md | 8 +- .../game-saves/conflicts.md | 106 ++-- .../player-progression/game-saves/overview.md | 17 +- .../game-saves/playstream-events.md | 106 ++++ .../player-progression/game-saves/toc.yml | 2 + .../images/171026-DelTitleGameManager.png | Bin 56379 -> 33306 bytes playfab-docs/release-notes/index.md | 15 +- scripts/validate-docs.ps1 | 576 ++++++++++++++++++ 30 files changed, 1761 insertions(+), 111 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/agents/docs-reviewer.md create mode 100644 .github/copilot-instructions.md create mode 100644 .github/instructions/api-references.instructions.md create mode 100644 .github/instructions/release-notes.instructions.md create mode 100644 .github/instructions/toc-files.instructions.md create mode 100644 .github/workflows/validate-docs.yml create mode 100644 CONTRIBUTING.md create mode 100644 playfab-docs/data-analytics/acting-data/media/get-segment-player-count.png rename playfab-docs/identity/player-identity/platform-specific-authentication/media/tutorials/xbox-add-on/{Xbox-live-add-on-page.png => xbox-live-add-on-page.png} (100%) create mode 100644 playfab-docs/live-service-management/game-configuration/segmentation/segmentation-player-count.md create mode 100644 playfab-docs/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pflobbygetrestrictinvitestolobbyowner.md create mode 100644 playfab-docs/player-progression/game-saves/playstream-events.md create mode 100644 scripts/validate-docs.ps1 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..198e45db6 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,23 @@ +## What changed + + + +## Related work items + + + +## Checklist + +- [ ] All new/modified articles have complete frontmatter (`author`, `title`, `description`, `ms.author`, `ms.topic`, `ms.date`, `ms.service`) +- [ ] `title` field is present (required for builds) +- [ ] `ms.date` updated on edited articles +- [ ] New articles added to the relevant `toc.yml` +- [ ] Images have descriptive alt-text for accessibility +- [ ] No raw HTML — use only standard Markdown and Learn extensions +- [ ] No broken links to other articles +- [ ] Cross-repo links use site-relative paths (no `.md` extension) +- [ ] Content is public-friendly (no confidential info or codenames) +- [ ] Build validation email reviewed — errors and warnings resolved +- [ ] Acrolinx score is 80+ (check automated PR test results) +- [ ] Ran `.\scripts\validate-docs.ps1` locally +- [ ] PR targets **main** diff --git a/.github/agents/docs-reviewer.md b/.github/agents/docs-reviewer.md new file mode 100644 index 000000000..77ba80b77 --- /dev/null +++ b/.github/agents/docs-reviewer.md @@ -0,0 +1,248 @@ +--- +name: docs-reviewer +description: > + Reviews changed PlayFab documentation files for compliance with authoring standards. + Validates frontmatter fields, markdown restrictions, TOC consistency, image alt-text, + heading structure, cross-repo linking rules, and writing style (Acrolinx). Reports + issues without modifying files. +tools: + - grep + - glob + - view + - powershell +--- + +# PlayFab Documentation Reviewer Agent + +You are a documentation reviewer for the PlayFab docs repo. Your job is to **review changed files** and **report issues** — never modify files. + +## How to Run a Review + +1. Get the list of changed `.md` and `toc.yml` files relative to `main`: + +``` +git --no-pager diff --name-only main -- 'playfab-docs/**/*.md' 'playfab-docs/**/toc.yml' +``` + +If that fails (e.g., no `main` branch locally), fall back to uncommitted changes: + +``` +git --no-pager diff --name-only HEAD -- 'playfab-docs/**/*.md' 'playfab-docs/**/toc.yml' +``` + +2. For each changed file, run the applicable checks below. +3. Produce a summary report at the end. + +--- + +## Checks for Markdown Files (`playfab-docs/**/*.md`) + +### 1. Required Frontmatter Fields + +Every `.md` file must have YAML frontmatter (`---` delimiters). The following fields are **always** required: + +| Field | Validation | +|---|---| +| `author` | Must be present and non-empty | +| `ms.author` | Must be present and non-empty | +| `ms.topic` | Must be one of: `article`, `conceptual`, `reference`, `include`, `hub-page`, `overview`, `release-notes` | +| `ms.date` | Must be present, format `MM/DD/YYYY` | +| `ms.service` | Must be `azure-playfab` | + +The following fields are required for **article pages** (any `ms.topic` value except `include`): + +| Field | Validation | +|---|---| +| `title` | Must be present and non-empty. **Build fails without it on article pages.** | +| `description` | Must be present, under 160 characters | + +> **Note:** `title` and `description` are not required for `ms.topic: include` files but are still allowed. + +Flag: `MISSING_FIELD`, `INVALID_VALUE`, or `EMPTY_FIELD` with the field name. + +### 2. Raw HTML Detection + +Scan the body (below frontmatter) for raw HTML tags. HTML is not permitted — only standard Markdown and Learn extensions. + +Skip content inside fenced code blocks (` ``` `). + +Common tags to detect: `

`, ``, ``, ``, `
`, `
`, `

`, ``, ``, `