Server Functions
Every ESX.* server function in ESX Legacy 1.16.4 with signatures, parameters, return values and examples. Players, callbacks, commands, jobs, items and vehicles.
These are the functions on the shared ESX object that only exist on the server. Get the object with ESX = exports['es_extended']:getSharedObject() or @es_extended/imports.lua, then call them from any server script. Functions that work on both sides (ESX.GetConfig, ESX.GetWeapon, ESX.Math, ESX.Table, ...) are on the shared functions page.
Overview
| Fact | Value |
|---|---|
| Side | Server |
| Source | es_extended/server/modules/* |
| Player object | xPlayer |
| Entity helpers | OneSync functions |
| Version | ESX Legacy 1.16.4 |
Global tables
| Table | Content |
|---|---|
ESX.Players | { [source] = xPlayer } for every loaded character. |
ESX.Jobs | { [jobName] = job }, each with a grades table keyed by grade as string. |
ESX.Items | { [itemName] = { label, weight, rare, canRemove } }. With ox_inventory this is ox_inventory's item list. |
Do not read these tables from other resources. The ESX object you receive through the export is a copy made at that moment, so the tables can be empty or stale. Use ESX.GetExtendedPlayers, ESX.GetJobs and ESX.GetItems instead.
Players
GetPlayerFromId
ESX.GetPlayerFromId(source)| Name | Type | Description |
|---|---|---|
source | number or string | Server ID. Converted with tonumber. |
Returns: xPlayer or nil if the player has no loaded character.
RegisterNetEvent("myshop:buy", function(itemName)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return end
-- validate itemName and price here
end)GetPlayerFromIdentifier
ESX.GetPlayerFromIdentifier(identifier)| Name | Type | Description |
|---|---|---|
identifier | string | Character identifier as stored in users.identifier (with charX: prefix when multicharacter is used). |
Returns: xPlayer or nil if that character is not online.
local xTarget = ESX.GetPlayerFromIdentifier(row.owner)
if xTarget then
xTarget.showNotification("Your vehicle was impounded")
endGetPlayerIdFromIdentifier
ESX.GetPlayerIdFromIdentifier(identifier)| Name | Type | Description |
|---|---|---|
identifier | string | Character identifier. |
Returns: number (server ID) or nil.
IsPlayerLoaded
ESX.IsPlayerLoaded(source)| Name | Type | Description |
|---|---|---|
source | number | Server ID. Must be a number, strings are not converted. |
Returns: boolean, true if an xPlayer exists for this ID.
GetExtendedPlayers
ESX.GetExtendedPlayers(key, value, minimal)| Name | Type | Description |
|---|---|---|
key | string? | Field to filter by. "job" compares job.name; any other key compares xPlayer[key], for example "group". |
value | any or table | Value to match. A list of values returns a table grouped by value. |
minimal | boolean? | true returns server IDs instead of xPlayer objects. |
Returns:
- No key: array of all xPlayers (or IDs).
- Single value: array of matching xPlayers (or IDs).
- List of values:
{ [value] = { xPlayer, ... } }.
-- All police officers
for _, xPlayer in ipairs(ESX.GetExtendedPlayers("job", "police")) do
xPlayer.showNotification("Robbery in progress at the Fleeca bank")
end
-- Grouped by job, only IDs
local byJob = ESX.GetExtendedPlayers("job", { "police", "ambulance" }, true)
print(#byJob.police, #byJob.ambulance)GetNumPlayers
ESX.GetNumPlayers(key, value)| Name | Type | Description |
|---|---|---|
key | string? | Same as GetExtendedPlayers. "job" uses a cached per-job counter. |
value | any or table | Value or list of values. |
Returns: number, or { [value] = count } when value is a list. Without arguments it returns #GetPlayers(), which also counts players who are still loading.
if ESX.GetNumPlayers("job", "police") < 2 then
return xPlayer.showNotification("Not enough police online", "error")
endGetPlayers
ESX.GetPlayers()Alias of the FiveM native GetPlayers(). Returns all connected server IDs as strings, including players without a loaded character.
Returns: string[]
Player
ESX.Player(src)| Name | Type | Description |
|---|---|---|
src | number or string | Server ID, or a character identifier. |
Only available in resources that load @es_extended/imports.lua. Returns a static proxy: every key you index is a function that calls the matching xPlayer method through the RunStaticPlayerMethod export. Fields like .job are not available, use getters.
Returns: static player or nil if not loaded.
local player = ESX.Player(source)
if player then
player.addAccountMoney("bank", 250, "Daily bonus")
endExtendedPlayers
ESX.ExtendedPlayers(key, value)Static-player version of GetExtendedPlayers. Same filters, returns static proxies. Only available through @es_extended/imports.lua.
for _, medic in ipairs(ESX.ExtendedPlayers("job", "ambulance")) do
medic.showNotification("New dispatch call")
endGetIdentifier
ESX.GetIdentifier(playerId)| Name | Type | Description |
|---|---|---|
playerId | number or string | Server ID. |
Returns the player's identifier of the type set in Config.Identifier (convar esx:identifier, default license) without the license: prefix. In FXDK mode it returns "ESX-DEBUG-LICENCE". Asserts if the player has no identifier of that type.
Returns: string
AddEventHandler("playerConnecting", function(_, _, deferrals)
local identifier = ESX.GetIdentifier(source)
print("Connecting: " .. identifier)
end)With multicharacter, users.identifier is char1:<identifier>, so ESX.GetIdentifier does not equal xPlayer.identifier. Use xPlayer.getIdentifier() for database lookups.
Callbacks
Server callbacks are handled by esx_lib. See the callbacks guide for the full flow with the client side.
RegisterServerCallback
ESX.RegisterServerCallback(name, handler)| Name | Type | Description |
|---|---|---|
name | string | Unique callback name, up to 200 characters. |
handler | function | function(source, cb, ...). Call cb(...) with the values to return. |
The resource that registers a name first owns it. Registering the same name from another resource throws an error; registering again from the same resource replaces the handler.
ESX.RegisterServerCallback("myshop:getBalance", function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
cb(xPlayer and xPlayer.getAccount("bank").money or 0)
end)The client calls it with ESX.TriggerServerCallback("myshop:getBalance", function(balance) end), see client functions.
DoesServerCallbackExist
ESX.DoesServerCallbackExist(name)Returns: boolean, whether a callback with this name is registered.
TriggerClientCallback
ESX.TriggerClientCallback(player, name, cb, ...)| Name | Type | Description |
|---|---|---|
player | number | Target server ID. |
name | string | Client callback name (registered with ESX.RegisterClientCallback). |
cb | function | Receives the values the client returns. |
... | any | Arguments for the client. |
ESX.TriggerClientCallback(source, "myscript:getStreetName", function(street)
print("Player is on " .. street)
end)AwaitClientCallback
ESX.AwaitClientCallback(player, name, ...)Same as TriggerClientCallback but yields the current thread and returns the client's values directly.
Returns: ... (whatever the client returned)
local street = ESX.AwaitClientCallback(source, "myscript:getStreetName")Events
TriggerClientEvent
ESX.TriggerClientEvent(eventName, playerIds, ...)| Name | Type | Description |
|---|---|---|
eventName | string | Client event name. |
playerIds | number or number[] | One server ID or an array of IDs. |
... | any | Event arguments. |
For an array, the arguments are serialized once and sent to every player, which is cheaper than calling TriggerClientEvent in a loop.
local officers = ESX.GetExtendedPlayers("job", "police", true)
ESX.TriggerClientEvent("dispatch:client:alert", officers, { code = "10-31", coords = coords })Commands
RegisterCommand
ESX.RegisterCommand(name, group, cb, allowConsole, suggestion)| Name | Type | Description |
|---|---|---|
name | string or string[] | Command name, or a list of aliases that share the same handler. |
group | string or string[] | Group(s) allowed to use it. ESX adds add_ace group.<group> command.<name> allow. |
cb | function | function(xPlayer, args, showError). xPlayer is false when run from the console. |
allowConsole | boolean? | Allow the server console to run it. |
suggestion | table? | { help, validate, arguments } for chat suggestions and argument parsing. |
Each entry in suggestion.arguments is { name, help, type, Validator? }:
type | Parsed into args[name] |
|---|---|
number | tonumber(arg), error if not numeric |
player | the target's xPlayer (me = yourself), error if not online |
playerId | the target's server ID (me = yourself), error if not online |
string | the raw string; numeric strings are rejected |
item | the item name, error if it is not in ESX.Items |
weapon | the upper-case weapon name from Config.Weapons |
coordinate | the first number found in the argument |
merge | this argument and everything after it, joined with spaces |
any | the raw string |
Set validate = true to require the exact number of arguments. Validator = { validate = function(value) return true end, err = "message" } adds a custom check per argument. showError(msg) shows a notification to the player, or prints to the console.
Registering an existing name again overrides the previous handler and prints a warning.
ESX.RegisterCommand("givecash", "admin", function(xPlayer, args, showError)
args.target.addMoney(args.amount, "Admin gift")
showError(("Gave $%d to %s"):format(args.amount, args.target.getName()))
end, true, {
help = "Give cash to a player",
validate = true,
arguments = {
{ name = "target", help = "Player ID", type = "player" },
{ name = "amount", help = "Amount", type = "number", Validator = {
validate = function(value) return value > 0 end,
err = "Amount must be positive",
} },
},
})The list of built-in commands is on the commands page.
Jobs
GetJobs
ESX.GetJobs(jobType)| Name | Type | Description |
|---|---|---|
jobType | string, string[] or nil | Only return jobs of this type (for example "civ"). |
Waits until jobs are loaded, then returns { [jobName] = job }. Each job contains the columns of its jobs row (name, label, type, ...) plus grades, keyed by grade as string.
for name, job in pairs(ESX.GetJobs()) do
print(name, job.label)
endDoesJobExist
ESX.DoesJobExist(job, grade)| Name | Type | Description |
|---|---|---|
job | string | Job name. |
grade | number or string | Grade number. |
Waits until jobs are loaded.
Returns: boolean
if ESX.DoesJobExist("police", 4) then
xPlayer.setJob("police", 4)
endRefreshJobs
ESX.RefreshJobs()Reloads every job and grade from the jobs and job_grades tables. Jobs without grades are skipped. If unemployed (or its grade 0) is missing, a fallback is created. Fires esx:jobsRefreshed.
RefreshJob
ESX.RefreshJob(jobName)| Name | Type | Description |
|---|---|---|
jobName | string | Job to reload from the database. |
Reloads one job and calls xPlayer.refreshJob() for every online member. Fires esx:jobRefreshed (jobName, job). If the job or its grades are gone, it is removed, its members become unemployed and esx:jobRemoved fires.
Returns: boolean, true if the job was refreshed.
MySQL.update.await("UPDATE job_grades SET salary = ? WHERE job_name = ? AND grade = ?", { 900, "police", 2 })
ESX.RefreshJob("police")CreateJob
ESX.CreateJob(name, label, grades, jobType)| Name | Type | Description |
|---|---|---|
name | string | Job name. |
label | string | Display label. |
grades | table[] | { grade, name, label, salary, skin_male?, skin_female? } entries. |
jobType | string? | Job type. Defaults to "civ". |
Inserts the job and any missing grades into the database in one transaction and adds them to ESX.Jobs. If the job exists, only new grades are added and the existing label and type are kept. Fires esx:jobCreated.
Returns: boolean, false if arguments are missing, nothing new was inserted, or the transaction failed.
ESX.CreateJob("baker", "Baker", {
{ grade = 0, name = "trainee", label = "Trainee", salary = 150 },
{ grade = 1, name = "baker", label = "Baker", salary = 300 },
{ grade = 2, name = "boss", label = "Owner", salary = 500 },
})See create a job.
Items
GetItems
ESX.GetItems()Returns: { [itemName] = { label, weight, rare, canRemove } }
GetItemLabel
ESX.GetItemLabel(item)Returns: string or nil (prints a warning for unknown items). With ox_inventory the label comes from exports.ox_inventory:Items(item).
xPlayer.showNotification(("You received %s"):format(ESX.GetItemLabel("bread")))AddItems
ESX.AddItems(items)| Name | Type | Description |
|---|---|---|
items | table[] | { name, label, weight?, rare?, canRemove? } entries. weight defaults to 1, rare to false, canRemove to true. |
Inserts new items into the items table (INSERT IGNORE), registers them in ESX.Items and refreshes online inventories. Items that already exist or have invalid fields are skipped. Not available with ox_inventory.
ESX.AddItems({
{ name = "coffee", label = "Coffee", weight = 0.3 },
{ name = "donut", label = "Donut", weight = 0.2 },
})RefreshItems
ESX.RefreshItems()Reloads all items from the items table and removes unknown items from online players. Not available with ox_inventory.
Returns: number, the number of items loaded.
RegisterUsableItem
ESX.RegisterUsableItem(item, cb)| Name | Type | Description |
|---|---|---|
item | string | Item name. |
cb | function | function(source, itemName, ...), called when the player uses the item. |
ESX does not remove the item for you. Remove it inside the callback.
ESX.RegisterUsableItem("bandage", function(source)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer or not xPlayer.removeInventoryItem("bandage", 1) then return end
TriggerClientEvent("myhealth:client:heal", source, 25)
end)UseItem
ESX.UseItem(source, item, ...)Runs the registered usable callback for item as if the player used it. Does not check whether the player owns the item. Errors inside the callback are caught and printed.
GetUsableItems
ESX.GetUsableItems()Returns: { [itemName] = true } for every registered usable item.
CreatePickup
ESX.CreatePickup(itemType, name, count, label, playerId, components, tintIndex, coords, bucket)| Name | Type | Description |
|---|---|---|
itemType | string | "item_standard", "item_account" or "item_weapon". |
name | string | Item, account or weapon name. |
count | number | Amount, or ammo for weapons. |
label | string | Text shown on the pickup. |
playerId | number? | Player that dropped it. Used for position, routing bucket and per-player limits. |
components | table? | Weapon components (item_weapon only). |
tintIndex | number? | Weapon tint (item_weapon only). |
coords | vector3, vector4 or table | Position. Required when playerId is not given. |
bucket | number? | Routing bucket. Defaults to the player's bucket, or 0. |
Pickups expire after 30 minutes. ESX limits them to 50 per player, 250 per 100 m grid cell and 5000 in total. Not available with ox_inventory.
Returns: pickup ID (number) or nil when a limit is reached or no position is known.
ESX.CreatePickup("item_standard", "bread", 3, "Bread x3", nil, nil, nil, vector3(215.0, -810.0, 30.7))Vehicles
GetVehicleType
ESX.GetVehicleType(model, player, cb)| Name | Type | Description |
|---|---|---|
model | string or number | Model name or hash. |
player | number? | A player to ask when the type is not cached yet. |
cb | function? | Receives the type. Without it the function yields and returns the type. |
Returns the server vehicle type for CreateVehicleServerSetter: "automobile", "bike", "boat", "heli", "plane", "submarine", "trailer" or "train". Unknown models without a player return nil. The server console command clearvehicletypes clears the cache.
local vehicleType = ESX.GetVehicleType("t20", source)CreateExtendedVehicle
ESX.CreateExtendedVehicle(owner, plate, coords)| Name | Type | Description |
|---|---|---|
owner | string | Owner identifier (owned_vehicles.owner). |
plate | string | Plate of a stored owned vehicle. |
coords | vector4 | Spawn position and heading. |
Spawns an owned vehicle from owned_vehicles with its saved properties, marks it as not stored and tracks it. Returns the existing object if that plate is already out. Fires esx:createdExtendedVehicle.
Returns: extended vehicle object or nil.
| Method | Description |
|---|---|
vehicle:isValid() | true while the entity still exists and matches owner and plate. Deletes the record otherwise. |
vehicle:getPlate() / getNetId() / getEntity() / getModelHash() / getOwner() | Getters. |
vehicle:setPlate(newPlate) | Updates the database, entity and state bag. Returns boolean. |
vehicle:setProps(props) | Saves new properties and syncs them. Returns boolean. |
vehicle:setOwner(identifier) | Transfers ownership in the database. Returns boolean. |
vehicle:delete(garageName?, isImpound?) | Deletes the entity and marks the vehicle as stored (in parking or pound). |
local vehicle = ESX.CreateExtendedVehicle(xPlayer.identifier, "ESX 123", vector4(215.8, -810.1, 30.7, 160.0))
if vehicle then
print("Spawned with net ID " .. vehicle:getNetId())
endGetExtendedVehicleFromPlate
ESX.GetExtendedVehicleFromPlate(plate)Returns: the extended vehicle object for a spawned plate, or nil.
local vehicle = ESX.GetExtendedVehicleFromPlate("ESX 123")
if vehicle then
vehicle:delete("legion_garage")
endPlayer function overrides
RegisterPlayerFunctionOverrides
ESX.RegisterPlayerFunctionOverrides(index, overrides)| Name | Type | Description |
|---|---|---|
index | string | Name of the override set. |
overrides | table | { [methodName] = function(self) return function(...) end end } |
Each entry is a factory that receives the xPlayer and returns the new method. All registered sets are applied to every xPlayer created afterwards. ESX uses this for its ox_inventory bridge.
ESX.RegisterPlayerFunctionOverrides("myOverrides", {
getName = function(self)
return function()
return ("[%s] %s"):format(self.job.label, self.name)
end
end,
})SetPlayerFunctionOverride
ESX.SetPlayerFunctionOverride(index)No effect in 1.16.4
This only stores index in Config.PlayerFunctionOverride, which es_extended no longer reads. Every registered override set is applied regardless.
Logging and debug
DiscordLog
ESX.DiscordLog(name, title, color, message)| Name | Type | Description |
|---|---|---|
name | string | Webhook key in Config.DiscordLogs.Webhooks. Falls back to default. |
title | string | Embed title. |
color | string | Color key in Config.DiscordLogs.Colors. |
message | string | Embed description. |
ESX.DiscordLog("UserActions", "Bank robbery", "red", ("%s started a robbery"):format(xPlayer.getName()))See the logs config.
DiscordLogFields
ESX.DiscordLogFields(name, title, color, fields)| Name | Type | Description |
|---|---|---|
fields | table[] | Discord embed fields { name, value, inline? }. Values are converted with tostring. |
Other parameters are the same as DiscordLog.
ESX.DiscordLogFields("UserActions", "Item sold", "green", {
{ name = "Player", value = xPlayer.getName(), inline = true },
{ name = "Item", value = "gold_bar", inline = true },
{ name = "Price", value = 2500, inline = true },
})Trace
ESX.Trace(msg)Prints [TRACE] msg to the server console only when Config.EnableDebug is true.
Common issues
ESX.Playeris nil: you did not add@es_extended/imports.luatoshared_scripts.- Empty
ESX.Jobsin your resource: read jobs withESX.GetJobs(), which also waits until they are loaded. AddItems,RefreshItemsorCreatePickupis nil: ox_inventory is running, so the default inventory functions are not defined.
Related
Frequently asked questions
Independent documentation
Last updated on
Logs Config
Configure Discord webhook logging in ESX Legacy. Webhook names, embed colors, which ESX features log where, and how to log from your own resources.
xPlayer
Complete ESX Legacy xPlayer reference. Every server-side player method for money, accounts, inventory, jobs, weapons, metadata and notifications, verified against 1.16.4.