# CFX::ADD_STATE_BAG_CHANGE_HANDLER

- **Hash:** `0x5BA35AAF`
- **Namespace:** CFX
- **Runtime name (Lua/JS):** `AddStateBagChangeHandler`
- **Side:** shared (Cfx runtime native)
- **Name status:** official
- **Documentation:** described with examples
- **URL:** https://natives.borderlinerp.com/natives/CFX/ADD_STATE_BAG_CHANGE_HANDLER

## Signature

```c
int ADD_STATE_BAG_CHANGE_HANDLER(char* keyFilter, char* bagFilter, func handler);
```

## Parameters

- `keyFilter` (`char*`) — The key to check for, or null for no filter.
- `bagFilter` (`char*`) — The bag ID to check for such as `entity:65535`, or null for no filter.
- `handler` (`func`) — The handler function.

## Returns

`int` — A cookie to remove the change handler.

## Description

*Source: Cfx.re native reference*

Adds a handler for changes to a state bag.

The function called expects to match the following signature:

```ts
function StateBagChangeHandler(bagName: string, key: string, value: any, reserved: number, replicated: boolean);
```

*   **bagName**: The internal bag ID for the state bag which changed. This is usually `player:Source`, `entity:NetID`
    or `localEntity:Handle`.
*   **key**: The changed key.
*   **value**: The new value stored at key. The old value is still stored in the state bag at the time this callback executes.
*   **reserved**: Currently unused.
*   **replicated**: Whether the set is meant to be replicated.

At this time, the change handler can't opt to reject changes.

If bagName refers to an entity, use [GET_ENTITY_FROM_STATE_BAG_NAME](#\_0x4BDF1867) to get the entity handle
If bagName refers to a player, use [GET_PLAYER_FROM_STATE_BAG_NAME](#\_0xA56135E0) to get the player handle

## Usage

### Lua

```lua
local retval = AddStateBagChangeHandler(keyFilter, bagFilter, handler)

-- always available, by hash
local retval = Citizen.InvokeNative(0x5ba35aaf, keyFilter, bagFilter, handler, Citizen.ResultAsInteger())
```

### JavaScript

```js
const retval = AddStateBagChangeHandler(keyFilter, bagFilter, handler);

// by hash
const retval = Citizen.invokeNative('0x5ba35aaf', keyFilter, bagFilter, handler, Citizen.returnResultAnyway(), Citizen.resultAsInteger());
```

### C#

```csharp
int retval = Function.Call<int>((Hash)0x5ba35aaf, keyFilter, bagFilter, handler);
```

## Examples

*Source: Cfx.re native reference*

```js
AddStateBagChangeHandler("blockTasks", null, async (bagName, key, value /* boolean */) => {
    let entity = GetEntityFromStateBagName(bagName);
    // Whoops, we don't have a valid entity!
    if (entity === 0) return;
    // We don't want to freeze the entity position if the entity collision hasn't loaded yet
    while (!HasCollisionLoadedAroundEntity(entity)) {
        // The entity went out of our scope before the collision loaded
        if (!DoesEntityExist(entity)) return;
        await Delay(250);
    }
    SetEntityInvincible(entity, value)
    FreezeEntityPosition(entity, value)
    TaskSetBlockingOfNonTemporaryEvents(entity, value)
})
```

*Source: Cfx.re native reference*

```lua
AddStateBagChangeHandler("blockTasks", nil, function(bagName, key, value) 
    local entity = GetEntityFromStateBagName(bagName)
    -- Whoops, we don't have a valid entity!
    if entity == 0 then return end
    -- We don't want to freeze the entity position if the entity collision hasn't loaded yet
    while not HasCollisionLoadedAroundEntity(entity) do
        -- The entity went out of our scope before the collision loaded
        if not DoesEntityExist(entity) then return end
        Wait(250)
    end
    SetEntityInvincible(entity, value)
    FreezeEntityPosition(entity, value)
    TaskSetBlockingOfNonTemporaryEvents(entity, value)
end)
```

*Source: Cfx.re native reference*

```cs
AddStateBagChangeHandler("blockTasks", null,
    new Action<string, string, object, int, bool>
    (async (bagName, key, value, res, rep) =>
    {
        bool val = (bool)value;

        var entity = GetEntityFromStateBagName(bagName);
        //-- Whoops, we don't have a valid entity!
        if (entity == 0) return;
        //-- We don't want to freeze the entity position if the entity collision hasn't loaded yet
        while (!HasCollisionLoadedAroundEntity(entity))
        {
            //--The entity went out of our scope before the collision loaded
            if (!DoesEntityExist(entity)) return;

            await Delay(250);
        }
        SetEntityInvincible(entity, val);
        FreezeEntityPosition(entity, val);
        TaskSetBlockingOfNonTemporaryEvents(entity, val);
    }));
```

## See also

- [CFX::REMOVE_STATE_BAG_CHANGE_HANDLER](https://natives.borderlinerp.com/natives/CFX/REMOVE_STATE_BAG_CHANGE_HANDLER.md) — Removes a handler for changes to a state bag.

*Sources: Cfx.re native reference.*
