Skip to main content

PlayerAssetOwnershipTracker

Tracks whether a player owns a given asset. Ownership resolves from an async cloud query (see PlayerAssetOwnershipTracker:SetQueryOwnershipCallback) plus session purchases, with an optional local override layered on top.

The override (see PlayerAssetOwnershipTracker:SetOwnershipOverride) is an authoritative layer: when set it wins over the cloud query and session purchases, forcing ownership on (true) or off (false). It is stored in a server-owned JSONAttributeValue on the player that Roblox replicates read-only to clients, so every realm applies the same overrides but only the server can assign them -- a player can never grant themselves ownership.

Functions

SetOwnershipOverride

PlayerAssetOwnershipTracker.SetOwnershipOverride(
selfany,
idOrKeynumber | string,
ownsAssetboolean?
) → ()

Sets a server-authoritative override for the player's ownership of the asset. When set, the override wins over the cloud query and any session purchase, forcing ownership on (true) or off (false). Passing nil clears the override so ownership falls back to the cloud query again (equivalent to PlayerAssetOwnershipTracker.ClearOwnershipOverride).

The override is published into a replicated attribute and applied on every realm, so it drives client-side ownership-gated UI. Only the server can assign it: the client-facing service exposes no setter and GameProductService.SetPlayerOwnershipOverride guards the server realm, so a player can never grant themselves ownership. Callers should go through that service, never here directly.

ClearOwnershipOverride

PlayerAssetOwnershipTracker.ClearOwnershipOverride(
selfany,
idOrKeynumber | string
) → ()

Clears any local ownership override for the asset, so ownership falls back to the cloud query. Equivalent to SetOwnershipOverride(idOrKey, nil).

_observeOwnsAssetId

PlayerAssetOwnershipTracker._observeOwnsAssetId(
selfany,
assetIdnumber
) → Observable<boolean>

Observes ownership of a resolved numeric asset id, layering the local override on top of the cloud query. When an override is present it wins and short-circuits the query; when it is cleared, ownership falls back to the cloud query and owned-asset set.

_observeBaseOwnsAssetId

PlayerAssetOwnershipTracker._observeBaseOwnsAssetId(
selfany,
assetIdnumber
) → Observable<boolean>

Observes ownership of a numeric asset id from the cloud query and owned-asset set only, without applying any override. Only fires once ownership status has been resolved.

SetQueryOwnershipCallback

PlayerAssetOwnershipTracker:SetQueryOwnershipCallback(promiseOwnsAssetfunction) → ()

Sets the callback which will query ownership

SetOwnership

PlayerAssetOwnershipTracker:SetOwnership(
idOrKeynumber,
ownsAssetboolean
) → ()

Sets the players ownership of a the asset

PromiseOwnsAsset

PlayerAssetOwnershipTracker:PromiseOwnsAsset(idOrKeystring | number) → Promise<boolean>

Promises true if the user owns the asset and false otherwise

ObserveOwnsAsset

PlayerAssetOwnershipTracker:ObserveOwnsAsset(idOrKeynumber | number) → Observable<boolean>

Observes whether the player owns the asset or not

Show raw api
{
    "functions": [
        {
            "name": "SetQueryOwnershipCallback",
            "desc": "Sets the callback which will query ownership",
            "params": [
                {
                    "name": "promiseOwnsAsset",
                    "desc": "",
                    "lua_type": "function"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 102,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        },
        {
            "name": "_warnQueryFailed",
            "desc": "Names an asset this tracker could not answer for. Reached once per query rather than once per\nconsumer of it: every caller and every subscriber attaches its own continuation to the same cached\nquery, so a rejection nobody handles is reported once per continuation -- hundreds of anonymous\n\"[Promise] - Uncaught exception\" lines for one failure.\n\nA query never made -- no callback for this realm -- is not reported: the rejection it returns says\nso in full, and a realm that cannot ask is not a fault.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "assetId",
                    "desc": "",
                    "lua_type": "number"
                },
                {
                    "name": "err",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [],
            "function_type": "static",
            "private": true,
            "source": {
                "line": 126,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        },
        {
            "name": "_consumeObservedQueryFailure",
            "desc": "Swallows a query failure on behalf of one subscriber. Named rather than inline because it is the\nwhole of what stops the noise: [PlayerAssetOwnershipTracker._warnQueryFailed] has already named the\nfailure once, and every subscriber after it lands on the same rejection with nothing to add.\n\nNothing is emitted, so the observable stays silent -- unresolved, which is not the same as \"does not\nown it\".",
            "params": [
                {
                    "name": "_self",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "_err",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [],
            "function_type": "static",
            "private": true,
            "source": {
                "line": 153,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        },
        {
            "name": "SetOwnership",
            "desc": "Sets the players ownership of a the asset",
            "params": [
                {
                    "name": "idOrKey",
                    "desc": "",
                    "lua_type": "number"
                },
                {
                    "name": "ownsAsset",
                    "desc": "",
                    "lua_type": "boolean"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 206,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        },
        {
            "name": "SetOwnershipOverride",
            "desc": "Sets a server-authoritative override for the player's ownership of the asset. When set, the\noverride wins over the cloud query and any session purchase, forcing ownership on (`true`) or off\n(`false`). Passing `nil` clears the override so ownership falls back to the cloud query again\n(equivalent to [PlayerAssetOwnershipTracker.ClearOwnershipOverride]).\n\nThe override is published into a replicated attribute and applied on every realm, so it drives\nclient-side ownership-gated UI. Only the server can assign it: the client-facing service exposes\nno setter and [GameProductService.SetPlayerOwnershipOverride] guards the server realm, so a player\ncan never grant themselves ownership. Callers should go through that service, never here directly.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "idOrKey",
                    "desc": "",
                    "lua_type": "number | string"
                },
                {
                    "name": "ownsAsset",
                    "desc": "",
                    "lua_type": "boolean?"
                }
            ],
            "returns": [],
            "function_type": "static",
            "source": {
                "line": 237,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        },
        {
            "name": "ClearOwnershipOverride",
            "desc": "Clears any local ownership override for the asset, so ownership falls back to the cloud\nquery. Equivalent to `SetOwnershipOverride(idOrKey, nil)`.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "idOrKey",
                    "desc": "",
                    "lua_type": "number | string"
                }
            ],
            "returns": [],
            "function_type": "static",
            "source": {
                "line": 297,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        },
        {
            "name": "PromiseOwnsAsset",
            "desc": "Promises true if the user owns the asset and false otherwise",
            "params": [
                {
                    "name": "idOrKey",
                    "desc": "",
                    "lua_type": "string | number"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Promise<boolean>"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 309,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        },
        {
            "name": "ObserveOwnsAsset",
            "desc": "Observes whether the player owns the asset or not",
            "params": [
                {
                    "name": "idOrKey",
                    "desc": "",
                    "lua_type": "number | number"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<boolean>"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 344,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        },
        {
            "name": "_observeOwnsAssetId",
            "desc": "Observes ownership of a resolved numeric asset id, layering the local override on top of\nthe cloud query. When an override is present it wins and short-circuits the query; when it\nis cleared, ownership falls back to the cloud query and owned-asset set.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "assetId",
                    "desc": "",
                    "lua_type": "number"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<boolean>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 381,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        },
        {
            "name": "_observeBaseOwnsAssetId",
            "desc": "Observes ownership of a numeric asset id from the cloud query and owned-asset set only,\nwithout applying any override. Only fires once ownership status has been resolved.",
            "params": [
                {
                    "name": "self",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "assetId",
                    "desc": "",
                    "lua_type": "number"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<boolean>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 405,
                "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
            }
        }
    ],
    "properties": [],
    "types": [],
    "name": "PlayerAssetOwnershipTracker",
    "desc": "Tracks whether a player owns a given asset. Ownership resolves from an async cloud\nquery (see [PlayerAssetOwnershipTracker:SetQueryOwnershipCallback]) plus session\npurchases, with an optional local override layered on top.\n\nThe override (see [PlayerAssetOwnershipTracker:SetOwnershipOverride]) is an authoritative layer:\nwhen set it wins over the cloud query and session purchases, forcing ownership on (`true`) or off\n(`false`). It is stored in a server-owned [JSONAttributeValue] on the player that Roblox\nreplicates read-only to clients, so every realm applies the same overrides but only the server\ncan assign them -- a player can never grant themselves ownership.",
    "source": {
        "line": 15,
        "path": "src/gameproductservice/src/Shared/Ownership/PlayerAssetOwnershipTracker.lua"
    }
}