Understanding State Bags in FiveM/RedM: A Complete Guide
- Published on
- • 5 mins read•--- views
Understanding State Bags in FiveM/RedM: A Complete Guide
Introduction
State Bags are a powerful feature in FiveM/RedM that enable efficient data synchronization across multiple players and entities. Introduced in version v2843 as a OneSync feature, State Bags provide a more robust alternative to traditional Decors, offering server-side access and modification capabilities.
Prerequisites
Before diving into State Bags, ensure you have:
- OneSync enabled (State Bags won't work without it)
- Basic understanding of FiveM/RedM scripting
- Familiarity with Lua programming
Types of State Bags
There are three main types of State Bags in FiveM/RedM:
- Entity State Bags
- Attached to specific entities
- Controlled by entity owner and server
- Player State Bags
- Specific to players
- Can be written by the player and server
- Global State Bags
- Server-wide state
- Server-set, client-read
- Shared across all resources
Basic Usage
Entity State Bags
-- Server-side
local vehicle = GetVehiclePedIsIn(ped, false)
local state = Entity(vehicle).state
-- Setting state
state.damage = 100
-- Getting state
local currentDamage = state.damage
-- Setting with replication control
Entity(vehicle).state:set('damage', 100, true) -- replicate to clients
Player State Bags
-- Server-side
local player = Player(source).state
player.health = 100
-- Client-side
LocalPlayer.state.health = 100
-- Accessing other player's state
local playerHealth = Player(id).state.health
-- Replicating from client
LocalPlayer.state:set('health', 75, true) -- replicate to server
Global State Bags
-- Server-side setting
GlobalState.weatherType = 'RAIN'
-- Client-side reading
local currentWeather = GlobalState.weatherType
-- Note: Clients cannot modify GlobalState
Replication Rules
Entity State Replication
Server-Side
-- Automatically replicates to all clients Entity(vehicle).state.fuel = 100 -- Optional non-replication Entity(vehicle).state:set('localData', 'value', false)Client-Side
-- Local only by default Entity(vehicle).state.customData = 'value' -- Explicit replication Entity(vehicle).state:set('customData', 'value', true)
Player State Replication
-- Server controls replication
Player(source).state.isAlive = true -- replicates
-- Client needs explicit replication
LocalPlayer.state:set('isReady', true, true) -- replicates to server
State Bag Change Handlers
State Bag change handlers allow you to monitor and react to state changes in real-time.
-- Basic change handler
AddStateBagChangeHandler('health', nil, function(bagName, key, value, _unused, replicated)
print(string.format("Health changed to: %s", value))
end)
-- Entity-specific handler
AddStateBagChangeHandler('fuel', 'entity:5', function(bagName, key, value, _unused, replicated)
if value < 10 then
print("Low fuel warning!")
end
end)
Advanced Handler Example
-- Explosion handler based on state
AddStateBagChangeHandler('exploded', nil, function(bagName, key, value, _unused, replicated)
-- Only process when value is true
if not value then return end
-- Get entity from bag name
local entity = GetEntityFromStateBagName(bagName)
if entity == 0 then return end
-- Get coordinates and create explosion
local coords = GetEntityCoords(entity)
AddExplosion(coords, 0xFFFFFFFF, 1.0, true, false, 1.0)
end)
Best Practices and Limitations
State Access Optimization
-- Inefficient
local x = Entity(vehicle).state.data.x
local y = Entity(vehicle).state.data.y
-- Better Approach
local state = Entity(vehicle).state
local x = state.data.x
local y = state.data.y
Shallow State Limitations
-- Won't work (nested modification)
Entity(vehicle).state.data.subset = 'value'
-- Correct approach
Entity(vehicle).state['data:subset'] = 'value'
Data Size Considerations
-- For large data, use latent events instead
-- Bad:
Entity(vehicle).state.hugeData = veryLargeTable
-- Better:
TriggerLatentClientEvent('syncLargeData', player, 1000, veryLargeTable)
Practical Examples
Vehicle Damage System
-- Server-side initialization
RegisterNetEvent('vehicleSpawned', function(netId)
local vehicle = NetworkGetEntityFromNetworkId(netId)
Entity(vehicle).state.damage = 0
Entity(vehicle).state.engineHealth = 1000
end)
-- Client-side damage handler
AddStateBagChangeHandler('damage', nil, function(bagName, key, value)
local vehicle = GetEntityFromStateBagName(bagName)
if vehicle == 0 then return end
-- Apply visual damage
SetVehicleDamageModifier(vehicle, value / 100)
end)
Player Status System
-- Server-side player status
RegisterNetEvent('playerLoaded', function()
Player(source).state.hunger = 100
Player(source).state.thirst = 100
end)
-- Client-side status update
CreateThread(function()
while true do
Wait(60000) -- Every minute
LocalPlayer.state:set('hunger', (LocalPlayer.state.hunger or 100) - 1, true)
LocalPlayer.state:set('thirst', (LocalPlayer.state.thirst or 100) - 1.5, true)
end
end)
Global Weather System
-- Server-side weather control
CreateThread(function()
local weatherTypes = {'CLEAR', 'CLOUDY', 'RAIN', 'THUNDER'}
while true do
Wait(300000) -- Every 5 minutes
local newWeather = weatherTypes[math.random(#weatherTypes)]
GlobalState.currentWeather = newWeather
end
end)
-- Client-side weather sync
AddStateBagChangeHandler('currentWeather', nil, function(_, _, value)
SetWeatherTypeOverTime(value, 15.0)
end)
Troubleshooting Common Issues
State Not Syncing
-- Check network ownership if not NetworkGetEntityOwner(entity) then return endUndefined States
-- Always check if state exists local damage = Entity(vehicle).state.damage if damage == nil then damage = 0 endReplication Issues
-- Ensure proper replication flags LocalPlayer.state:set('status', 'ready', true) -- Must set true for client->server
Conclusion
State Bags provide a powerful and efficient way to synchronize data across your FiveM/RedM server. By following these best practices and understanding the limitations, you can create robust and performant systems for your server.
Remember key points:
- Use appropriate state bag types for your needs
- Be mindful of data size and replication
- Implement proper error handling
- Consider performance implications in high-traffic scenarios
Additional Resources
Join Our Community!
Get help, share ideas, get free scripts, and connect with other RedM enthusiasts in our Discord server.
Join Discord