I have developed a script that allows you to manage the sirens and flashing lights of French emergency vehicles on the driver and passenger side.
for the sound to be managed on the driver and passenger side I had to make each client (player) play their sound for this I go through events that will be executed by each player, after that we noticed that the sound was unloaded at 424 units as explained in the doc OneSync - Cfx.re Docs so we do a check every second on the server side on all vehicles that have a start siren and we check for each player if they are next to a vehicle on that it works the optimization on the client side and correct but on the server side we arrive at peaks of 2.60ms for 60 players and I would like to have the opinion of the developers here, what would I have done because I admit that if we lose performance on the server side the more players we have it will quickly become annoying
On the Fivem documentation regarding oneSync a playerEnteredScope event is played when the player enters the range of another player, it is a shame that there is not one that is executed when a player enters the loading range of an entity
Use state bags for such things: State bags - Cfx.re Docs
They can be attached to entities and will execute a state bag change handler when a player gets in scope (or the state bag is changed). No more need for manually checking who is in range etc. You simply set a value, it gets synced automatically.
local sirens = {}
local function playSiren(entity)
-- Prevent from playing siren twice
if sirens[tostring(entity)] then return false end
print('Play siren', 'State', Entity(entity).state['siren'])
sirens[tostring(entity)] = true
return true
end
local function stopSiren(entity)
sirens[tostring(entity)] = nil
print('Stop siren', 'State', Entity(entity).state['siren'])
end
AddStateBagChangeHandler('siren', nil, function(bagName, key, value, _, rep)
-- Handle only siren 'on' state
if value ~= true then return end
-- Get entity (stable alternative for GetEntityFromStateBagName(bagName))
local netId, _ = string.gsub(bagName, 'entity:', '')
netId = tonumber(netId)
local timeoutAt = GetGameTimer() + 1500
while not NetworkDoesEntityExistWithNetworkId(netId) do
Wait(0)
if GetGameTimer() >= timeoutAt then
return print('Timeout, entity network doesnt exist', netId)
end
end
local entity = NetworkGetEntityFromNetworkId(netId)
-- Ensure entity exists
if not DoesEntityExist(entity) then return print('Entity doesnt exist', entity) end
-- Ensure handler executed only once (local player replication)
local amOwner = NetworkGetEntityOwner(entity) == PlayerId()
if amOwner and replicated then return end
-- Ensure entity has the state assigned
while Entity(entity).state['siren'] ~= true do Wait(0) end
-- Play siren
if playSiren(entity) then
-- Wait entity exists and while siren is enabled
while DoesEntityExist(entity) and Entity(entity).state['siren'] == true do
Wait(200)
end
-- Stop siren
stopSiren(entity)
end
end)
RegisterCommand('sirenon', function()
local vehicle = GetVehiclePedIsIn(PlayerPedId())
if not DoesEntityExist(vehicle) then
return
end
Entity(vehicle).state:set('siren', true, true)
end, false)
RegisterCommand('sirenoff', function()
local vehicle = GetVehiclePedIsIn(PlayerPedId())
if not DoesEntityExist(vehicle) then
return
end
Entity(vehicle).state:set('siren', false, true)
end, false)
I used this before, but it’s not reliable in some cases like this one:
I think I found a bug with the state bag handler. With the given code, if one player stays on the server near an entity with the siren enabled, and another player joins the server and approaches the entity, the handler does execute for the second player, but the entity was 0 by calling GetEntityFromStateBagName(bagName)
I haven’t run into that issue for ages now. As from my own observation it is fixed.
But I know what you mean. Used to happen when it was first introduced.
Tested it before and double-checked it again just now, on server artifacts version 12817 and FiveM Client “Latest Unstable”. Issue is there.
I used this code:
local sirens = {}
local function playSiren(entity)
-- Prevent from playing siren twice
if sirens[tostring(entity)] then return false end
print('Play siren', 'State', Entity(entity).state['siren'])
sirens[tostring(entity)] = true
return true
end
local function stopSiren(entity)
sirens[tostring(entity)] = nil
print('Stop siren', 'State', Entity(entity).state['siren'])
end
AddStateBagChangeHandler('siren', nil, function(bagName, key, value, _, rep)
local entity = GetEntityFromStateBagName(bagName)
print('siren', bagName, key, value, _, rep, 'Entity:', entity, DoesEntityExist(entity))
if entity == 0 or rep == true then return end
-- Handle only siren 'on' state
if value ~= true then return end
-- Ensure entity has the state assigned
while Entity(entity).state['siren'] ~= true do Wait(0) end
-- Play siren
if playSiren(entity) then
-- Wait entity exists and while siren is enabled
while DoesEntityExist(entity) and Entity(entity).state['siren'] == true do
Wait(200)
end
-- Stop siren
stopSiren(entity)
end
end)
Hello,
I’m restarting the topic because people complained that they could no longer hear the sound and that they had to disconnect and reconnect to hear them. The server was at 70 players and I checked my code but it’s the StateBagHandler that is supposed to play as in your example, I also did a search on the forum but I can’t find anything similar or posts that are old and have been corrected
Thank you for your help
For example you use table VehicleData[netid] to store info about soundId’s by netId as a key, but the problem is that netId is a number and this may cause the issue of indexing the data. Try to convert netId to a string before doing anything with the table, like this VehicleData[tostring(netid)].
It’s hard to tell what’s wrong then. You need to debug this case, add some logs into the code. For example I would check first if sound id is given correctly:
print('Sound ID', soundId)
Then wait if someone will have issue and ask them for logs from F8 console.
hello,
so we tested and printed all the values ​​and we didn’t notice anything, the problem that my colleague pointed out to me was a bad use of the RequestScriptAudioBank so we modified a few lines of code and we didn’t get any feedback from the players, it was simply a bad manipulation on our part, thank you anyway for helping us especially for the state bags