FiveM Docs
es_extendedClientModules

Callbacks

How ESX Legacy callbacks work: TriggerServerCallback, AwaitServerCallback, RegisterServerCallback and client callbacks, with timeouts and limits.

Callbacks let one side ask the other side for data and get an answer back. The client asks the server with ESX.TriggerServerCallback or ESX.AwaitServerCallback, and the server answers through a handler registered with ESX.RegisterServerCallback. The reverse direction works the same way with client callbacks.

Overview

Resourcees_extended (implemented by esx_lib)
SideClient and server
Sourceclient/modules/callback.lua, server/modules/callback.lua

In ESX Legacy 1.16 the ESX callback functions are thin wrappers around xLib.callback from esx_lib. The ESX signatures (cb as first or second argument) still work, so old scripts do not need changes.

DirectionRegister onTrigger with
Client asks serverServer: ESX.RegisterServerCallbackClient: ESX.TriggerServerCallback, ESX.AwaitServerCallback
Server asks clientClient: ESX.RegisterClientCallbackServer: ESX.TriggerClientCallback, ESX.AwaitClientCallback

Client functions

ESX.TriggerServerCallback

ESX.TriggerServerCallback(eventName, callback, ...)

Calls a server callback and passes the response to callback. Does not block.

NameTypeDescription
eventNamestringCallback name.
callbackfunctionReceives the values the server passed to cb.
...anyArguments sent to the server handler.

Returns: nothing

client/main.lua
ESX.TriggerServerCallback('garage:getVehicles', function(vehicles)
    for i = 1, #vehicles do
        print(vehicles[i].plate)
    end
end, 'pillbox')

ESX.AwaitServerCallback

ESX.AwaitServerCallback(eventName, ...)

Calls a server callback and waits for the answer. Must run inside a thread (command handler, CreateThread, event handler).

NameTypeDescription
eventNamestringCallback name.
...anyArguments sent to the server handler.

Returns: every value the server passed to cb.

client/main.lua
RegisterCommand('mygarage', function()
    local vehicles = ESX.AwaitServerCallback('garage:getVehicles', 'pillbox')
    print(('You own %d vehicles here'):format(#vehicles))
end, false)

ESX.AwaitServerCallback throws an error when the callback does not exist or times out. Wrap it in pcall if your code must continue in that case.

ESX.RegisterClientCallback

ESX.RegisterClientCallback(eventName, callback)

Registers a callback the server can call on this client. The handler gets cb first, then the server's arguments. It is removed when your resource stops.

NameTypeDescription
eventNamestringCallback name (max. 200 characters).
callbackfunctionfunction(cb, ...). Call cb(...) once with the response.

Returns: nothing

client/main.lua
ESX.RegisterClientCallback('police:getStreetName', function(cb)
    local coords = GetEntityCoords(ESX.PlayerData.ped)
    local street = GetStreetNameFromHashKey(GetStreetNameAtCoord(coords.x, coords.y, coords.z))
    cb(street)
end)

ESX.DoesClientCallbackExist

ESX.DoesClientCallbackExist(eventName)

Returns: boolean, whether a callback with this name is registered in the local esx_lib registry.

Server functions

These are listed here so both halves are in one place. The full server reference is in Server functions.

ESX.RegisterServerCallback

ESX.RegisterServerCallback(eventName, callback)
NameTypeDescription
eventNamestringCallback name (max. 200 characters).
callbackfunctionfunction(source, cb, ...). Call cb(...) once with the response.

Returns: nothing

server/main.lua
ESX.RegisterServerCallback('garage:getVehicles', function(source, cb, garage)
    local xPlayer = ESX.GetPlayerFromId(source)
    if not xPlayer or type(garage) ~= 'string' then
        return cb({})
    end

    local vehicles = MySQL.query.await(
        'SELECT plate, vehicle FROM owned_vehicles WHERE owner = ? AND parking = ?',
        { xPlayer.identifier, garage }
    )
    cb(vehicles or {})
end)

ESX.TriggerClientCallback

ESX.TriggerClientCallback(player, eventName, callback, ...)
NameTypeDescription
playernumberServer id of the target player.
eventNamestringClient callback name.
callbackfunctionReceives the client's response.
...anyArguments for the client handler.

Returns: nothing

server/main.lua
ESX.TriggerClientCallback(source, 'police:getStreetName', function(street)
    print(('Player %s is on %s'):format(source, street))
end)

ESX.AwaitClientCallback

ESX.AwaitClientCallback(player, eventName, ...)

Blocking version of ESX.TriggerClientCallback. Returns: the values the client passed to cb.

ESX.DoesServerCallbackExist

ESX.DoesServerCallbackExist(eventName)

Returns: boolean

Timeouts and limits

SettingDefaultDescription
esx:callbackTimeout / xLib:callbackTimeout300000 msHow long the caller waits. 0 disables the timeout. Set on the server; it is replicated to clients.
xLib:callbackValidationGrace15000 msHow long an unknown callback name is given to appear before the caller gets "does not exist".
xLib:callbackBurst / xLib:callbackRate60 / 30 per secondPer-player rate limit for client to server callbacks.
xLib:callbackMaxInFlight8Open client to server callbacks per player.
xLib:callbackMaxPayloadBytes65536Max size of the arguments a client may send.
server.cfg
setr esx:callbackTimeout 30000

If a client exceeds the rate limit or payload size, or a server handler takes longer than the receiver timeout (30 s unless esx:callbackTimeout is set), the client gets false as the response.

Built-in callbacks

NameSideReturns
esx:getPlayerDataServerIdentifier, accounts, inventory, job, loadout, money, position and metadata of the caller.
esx:getOtherPlayerDataServerSame data for another player id. Admins only, otherwise nil.
esx:isUserAdminServertrue if the caller is an admin.
esx:getGameBuildServerValue of sv_enforceGameBuild (default 1604).
esx:getPlayerNamesServerCharacter names for a table of player ids.
esx:spawnVehicleServerDeprecated. Admin-only vehicle spawn, prints a warning.
esx:GetVehicleTypeClientVehicle type string for a model. Used by the server-side ESX.GetVehicleType.
local isAdmin = ESX.AwaitServerCallback('esx:isUserAdmin')

Security

Never trust callback arguments

Everything a client sends to ESX.RegisterServerCallback can be faked by a cheater. Validate types and ranges, look the player up with ESX.GetPlayerFromId(source), and check permissions and distances on the server. Never let a callback give money or items based on a value the client sent.

Common issues

  • Old code calls cb twice. Only the first call is used.
  • Server handler never calls cb. After the receiver timeout (30 s by default) the server answers with false, so the client gets false instead of your data.
  • "callback 'x' is already owned by resource 'y'". Two resources use the same name. Prefix names with your resource name.

Frequently asked questions

Independent documentation

esx-fivem.com is a community project and is not affiliated with the ESX Framework team. Facts on this page were checked against the upstream source. Official resources: docs.esx-framework.org and github.com/esx-framework.
Edit on GitHub

Last updated on

On this page