State Bags (or Entity State) are a modern networking feature in FiveM (requires OneSync) that allows you to store arbitrary key-value pairs on entities (players, vehicles, peds, objects) or globally. These values are automatically synchronized between the server and relevant clients.
They replace many traditional TriggerClientEvent patterns for syncing data like “is player handcuffed”, “vehicle fuel level”, or “job duty status”.
State bags are accessed via the .state property on an entity.
-- Set a value on a vehicle
local vehicle = GetVehiclePedIsIn(GetPlayerPed(source), false)
local ent = Entity(vehicle)
-- Set 'fuel' to 100.
-- The 'true' argument enables replication to clients.
ent.state:set('fuel', 100, true)
-- Set a value on a player
local playerEnt = Entity(GetPlayerPed(source))
playerEnt.state:set('isHandcuffed', true, true)local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
local ent = Entity(vehicle)
-- Access directly like a table
local fuel = ent.state.fuel
if fuel then
print("Current fuel:", fuel)
endGlobalState is a special state bag that is not attached to any specific entity but is available everywhere. It’s perfect for server-wide variables like “weather”, “server announcement”, or “event active”.
-- Server: Set global state
GlobalState.weather = "EXTRASUNNY"
-- Client: Read global state
print("Current weather:", GlobalState.weather)You can listen for changes to state bags using AddStateBagChangeHandler. This is useful for triggering visual effects or logic when a value changes.
-- Client Side: Listen for 'isHandcuffed' changes on any player
AddStateBagChangeHandler('isHandcuffed', nil, function(bagName, key, value, _reserved, replicated)
-- bagName format: "entity:12345" or "player:1"
local entity = GetEntityFromStateBagName(bagName)
-- Verify the entity exists and is a player
if entity == 0 then return end
if value == true then
-- Apply handcuff animation
print("Player handcuffed!")
else
-- Remove animation
print("Player released!")
end
end)When setting a state bag value, the third argument controls replication:
-- replicated: true = sends to clients
-- replicated: false = stays on server only
entity.state:set('secretKey', '12345', false) To allow a client to replicate a specific state key, use SetResourceKvp policy (advanced) or trust the client to trigger a server event to change the state. Best Practice: Always have the server set important game states.
For player entities, you can access state via the player’s server ID.
-- Server Side
local playerState = Player(source).state
playerState.job = "police"
-- Client Side
local myState = LocalPlayer.state
print(myState.job) -- prints "police"myScript:fuel instead of just fuel).| Feature | Syntax |
|---|---|
| Get Entity | Entity(entityHandle) |
| Get Player | Player(serverId) |
| Get Local Player | LocalPlayer |
| Set State | ent.state:set(key, value, replicated) |
| Get State | ent.state.key |
| Global State | GlobalState.key |
| Listen for Change | AddStateBagChangeHandler(...) |