esx_lib
esx_lib reference for ESX Legacy. Load xLib, use callbacks, cache, points, NUI, rate limiting, tokens, pub/sub and every module with signatures.
esx_lib is the official ESX utility library. It exposes a global xLib table that lazily loads modules (callbacks, player cache, points, NUI helpers, streaming, validation, rate limiting and more) into any resource that includes @esx_lib/imports.lua. es_extended itself is built on top of it, so every ESX Legacy server needs esx_lib started first.
Overview
| Fact | Value |
|---|---|
| Resource name | esx_lib (the loader hardcodes this name, do not rename the folder) |
| Version | 1.0.0 (legacyversion '1.16.3' in fxmanifest) |
| Side | Shared (client and server modules) |
| Dependencies | None. oxmysql is only needed by the server-side schema and catalog modules, which run inside es_extended. |
| Used by | es_extended, esx_identity, esx_inventory, esx_menu_default, esx_menu_dialog, esx_multicharacter, esx_progressbar, esx_skin, esx_whitelist |
| Global | xLib (with fields name, side, debug) |
Parts of esx_lib are adapted from ox_lib by Linden (LGPL-3.0). Those files carry the original notice in the source.
Installation and load order
esx_lib ships in the [core] folder of esx_core. Start it before es_extended:
ensure oxmysql
ensure esx_lib
ensure es_extendedTo use xLib in your own resource, add the import as a shared script and declare the dependency:
fx_version 'cerulean'
game 'gta5'
lua54 'yes'
shared_scripts {
'@esx_lib/imports.lua',
'@es_extended/imports.lua',
}
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }
dependencies {
'es_extended',
'esx_lib',
}How lazy loading works
imports.lua creates the xLib table with an __index metamethod. The first time you read xLib.<name>, it loads imports/<name>/shared.lua plus imports/<name>/client.lua or imports/<name>/server.lua from esx_lib and runs them inside your resource. Modules you never touch are never loaded.
If no module folder exists for a name, xLib returns a proxy that calls exports.esx_lib:<name>(...). This is how functions that must live in one central place (callback validation, pub/sub registry, triggerClientEvent) are shared by every resource.
Global require is replaced
imports.lua sets require = xLib.require in your resource. Plain require('module') therefore loads files from your resource through LoadResourceFile, not from the standard Lua package path. See require.
Module summary
| Module | Side | Purpose |
|---|---|---|
addKeybind | Client | Register key mappings with press and release handlers |
blips | Client | Create and remove map blips from an options table |
cache | Client | Cached ped, vehicle, seat, weapon, playerId, serverId, coords |
callback | Client, Server | Client/server callbacks with validation, timeouts and rate limits |
class | Shared | Minimal class system with constructor and new |
colors | Shared | ESX brand colors and UI theme from convars |
dui | Client | DUI (browser texture) class |
entity | Client | Closest entity and distance helpers, teleport |
game | Client | Spawn and delete vehicles and objects, closest player, ped mugshots |
interactions | Client | Shared "Interact" key (E by default) with conditional handlers |
isEnhanced | Shared | Detects the GTA V Enhanced build |
markerZone | Client | Marker plus interaction zone built on points |
math | Shared | Clamp, rounding, conversion, lerp, color and heading helpers |
medal | Client | Trigger a Medal.tv clip through the local Medal client |
nui | Client | SendNUIMessage, focus and NUI callback helpers |
onesync | Server | Players and entities in an area (server-side OneSync) |
overload | Shared | Type-based function overloading |
player | Server | Player ped, coords and distance checks |
point / points | Client | Proximity points with enter, leave and inside |
pubsub | Client, Server | Server-driven topic subscriptions |
rateLimiter | Server | Token bucket rate limiter |
raycast | Client | Raycasts from the camera |
require | Shared | Module loader, xLib.load and xLib.loadJson |
scaleform | Client | Freemode messages, breaking news, popup warnings |
schema | Server | Database column inspection and safe migrations (oxmysql) |
server | Server | Aliases for player distance checks |
streaming | Client | Request models, dicts, assets with timeout |
string | Shared | Case conversion, safe matching, randomHex, uuid |
table | Shared | Array and table helpers |
timeout | Shared | Cancellable setTimeout and clearTimeout |
token | Server | Single-use, expiring tokens |
validation | Shared, Server | Validate numbers, money, strings and player proximity |
vehiclePlate | Shared | Normalize, compare and generate plates |
verify | Shared | Runtime type checks |
waitFor | Shared | Yield until a function returns a value |
The catalog folder is not a regular module. es_extended loads imports/catalog/bootstrap.lua directly (see SQL catalog).
Callbacks
xLib.callback is the callback system ESX uses internally. ESX.TriggerServerCallback and ESX.RegisterServerCallback are compat wrappers around it (xLib.callback.registerCompat). For new code, use xLib directly or the ESX wrappers described in Callbacks.
xLib.callback.register
xLib.callback.register(name, cb)| Name | Type | Description |
|---|---|---|
name | string | Unique callback name (max 200 chars). A name owned by another resource raises an error. |
cb | function | Server: function(source, ...). Client: function(...). Its return values are sent back. |
Errors inside cb are printed with a stack trace and the caller receives false.
xLib.callback.await
-- client
local ... = xLib.callback.await(name, delay, ...)
-- server
local ... = xLib.callback.await(name, playerId, ...)| Name | Type | Description |
|---|---|---|
name | string | Callback name registered on the other side |
delay | number or false | Client only. Throttle in ms: further calls to the same name within this window return immediately without a request. |
playerId | number | Server only. Target player |
... | any | Arguments passed to the handler |
Yields the current thread and returns the handler's return values. Rejects with callback '<name>' does not exist if nothing is registered, or with a timeout error.
xLib.callback (with function)
xLib.callback(name, delayOrPlayerId, cb, ...)Same as await, but calls cb(...) with the results instead of yielding. Omitting cb prints a warning and falls back to await.
xLib.callback.register('myshop:getBalance', function(source, account)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return false end
return xPlayer.getAccount(account).money
end)xLib.callback.registerCompat
xLib.callback.registerCompat(name, cb, owner)Registers a handler with the legacy ESX signature: server function(source, cb, ...), client function(cb, ...). owner is the resource whose stop removes the handler. es_extended uses this for ESX.RegisterServerCallback and ESX.RegisterClientCallback.
Callback limits
Server callbacks are protected by per-player budgets. When a player exceeds them, the request is answered with false. All values are server convars.
| Convar | Default | Meaning |
|---|---|---|
xLib:callbackTimeout | falls back to esx:callbackTimeout, then 300000 ms | Await timeout. Replicated to clients when set. |
xLib:callbackBurst | 60 | Request bucket capacity per player |
xLib:callbackRate | 30 | Requests refilled per second |
xLib:callbackByteBurst | 262144 | Payload byte bucket per player |
xLib:callbackByteRate | 65536 | Bytes refilled per second |
xLib:callbackMaxPayloadBytes | 65536 | Max packed size of one request |
xLib:callbackMaxInFlight | 8 | Concurrent callbacks per player |
xLib:callbackMaxGlobalInFlight | 4096 | Concurrent callbacks server-wide |
xLib:callbackValidationGrace | 15000 | Delay before an unknown callback name is rejected (capped at half the timeout) |
xLib:callbackValidationWindow | 5000 | Window for counting invalid-name validations |
xLib:callbackValidationMaxRequests | 30 | Max invalid-name validations per window |
The server-side receiver also gives up after the configured timeout, or 30 seconds when none is set. Payloads are limited to 32 arguments, 2048 entries and 8 levels of nesting.
Client cache
local cache = xLib.cache| Key | Type | Description |
|---|---|---|
playerId | number | PlayerId() |
serverId | number | GetPlayerServerId(PlayerId()), resolved lazily |
ped | number | Current player ped |
vehicle | number or false | Current vehicle |
seat | number or false | Seat index (-1 is the driver) |
weapon | number or false | Selected weapon hash, false when unarmed |
coords | vector3 | Read live on every access |
esx_lib polls every 100 ms and triggers a local event xLib:cache:<key> with (value, previous) when ped, vehicle, seat or weapon change. Other resources update their copy from that event.
AddEventHandler('xLib:cache:vehicle', function(vehicle, previous)
if vehicle then
print('Entered vehicle', vehicle, 'seat', xLib.cache.seat)
else
print('Left vehicle', previous)
end
end)Points and marker zones
xLib.points.create
local handle = xLib.points.create(coords, distance, hidden, enter, leave, inside)| Name | Type | Description |
|---|---|---|
coords | vector3 | Point position |
distance | number | Radius that counts as "nearby" |
hidden | boolean? | Hidden points never trigger |
enter | function | Called once when the player enters the radius |
leave | function | Called once when the player leaves |
inside | function? | Called every frame while nearby, with the current distance |
Also available: xLib.points.remove(handle) and xLib.points.hide(handle, hidden). Proximity is scanned every 500 ms; the loop only runs every frame while at least one point with inside is active. Points are removed automatically when the creating resource stops.
xLib.point is the class form: xLib.point:new({ coords, distance, hidden, enter, leave, inside }) with methods :delete() and :toggle(hidden?). Its callbacks receive self.
xLib.markerZone.create
local zone = xLib.markerZone.create(data)| Field | Type | Description |
|---|---|---|
coords | vector3 or table | Zone center |
drawDistance | number? | Marker draw radius (alias distance), default 10.0 |
interactDistance | number? | Interaction radius (aliases actionDistance, enterDistance), default 1.5 |
exitDistance | number? | Radius to leave interaction, defaults to interactDistance |
marker | table or false | Marker options, false disables drawing |
hidden | boolean? | Start hidden |
canDraw / canInteract | function(distance)? | Extra conditions |
onEnter / onInside / onExit | function(distance)? | Interaction radius handlers |
onEnterPoint / onExitPoint | function? | Draw radius handlers |
Returns { handle, remove(), hide(hidden?), show() }, or nil when coords is invalid.
local zone = xLib.markerZone.create({
coords = vector3(25.7, -1347.3, 29.5),
interactDistance = 1.5,
onEnter = function()
ESX.TextUI('[E] Open shop')
end,
onExit = function()
ESX.HideUI()
end,
})Interactions and keybinds
xLib.addKeybind
local keybind = xLib.addKeybind(data)| Field | Type | Description |
|---|---|---|
name | string | Command name (registered as +name / -name) |
description | string | Label in the FiveM key bindings menu |
defaultMapper | string? | Input mapper, default keyboard |
defaultKey | string? | Default key |
disabled | boolean? | Start disabled |
onPressed / onReleased | function(self)? | Handlers, skipped while the pause menu is open |
The returned object has currentKey, isPressed, getCurrentKey(), isControlPressed(), disable(toggle) and remove().
xLib.interactions
esx_lib registers one keybind named esx_interact (default E) and triggers the local event xLib:interact when it is pressed. xLib.interactions lets many resources share that key:
xLib.interactions.register(name, onPress, condition)
xLib.interactions.remove(name)
local key = xLib.interactions.getInteractKey() -- e.g. "E"Every registered interaction whose condition() returns true runs onPress(). Interactions are removed when their resource stops.
NUI helpers
| Function | Description |
|---|---|
xLib.nui.send(message, data?) | Sends a table as-is, or { action = message, data = data } when message is a string |
xLib.nui.focus(hasFocus, hasCursor?, keepInput?) | SetNuiFocus; cursor defaults to hasFocus |
xLib.nui.open(message?, focus?, cursor?, keepInput?) | Send and focus (skip focus with focus = false) |
xLib.nui.close(message?) | Send and drop focus |
xLib.nui.ok(data?) / xLib.nui.fail(error, code?) | Build { ok, data } / { ok = false, error, code } responses |
xLib.nui.register(name, handler) | RegisterNUICallback wrapper with error handling |
handler(data, reply) can return a value (sent as response, nil becomes ok()), or call reply(response) later. Handlers that declare two parameters and return nil are treated as deferred; they time out after xLib:nuiDeferTimeout ms (default 10000) and reply fail('timeout', 'timeout').
Streaming
All functions accept an optional cb. Without it they yield and return the loaded asset; with it they call cb(asset). Requests time out after xLib:streamingTimeout ms (default 10000).
| Function | Returns |
|---|---|
xLib.streaming.requestModel(modelHash, cb?) | Model hash or nil |
xLib.streaming.requestModelWithSpinner(modelHash, message?, cb?) | Model hash or nil |
xLib.streaming.requestStreamedTextureDict(textureDict, cb?) | Dict name |
xLib.streaming.requestNamedPtfxAsset(assetName, cb?) | Asset name |
xLib.streaming.requestAnimSet(animSet, cb?) | Anim set |
xLib.streaming.requestAnimDict(animDict, cb?) | Anim dict |
xLib.streaming.requestWeaponAsset(weaponHash, cb?) | Weapon hash |
xLib.streaming.requestAudioBank(bankName, cb?) | Bank name |
Game and entity helpers (client)
| Function | Description |
|---|---|
xLib.game.spawnVehicle(model, coords, heading, cb?, networked?) | Spawns a vehicle (networked by default). Yields and returns the handle when cb is omitted. Errors if coords is more than 424 units from the player. |
xLib.game.spawnLocalVehicle(model, coords, heading, cb?) | Non-networked vehicle |
xLib.game.spawnObject(model, coords, cb?, networked?) | Spawns an object |
xLib.game.spawnLocalObject(model, coords, cb?) | Non-networked object |
xLib.game.deleteVehicle(vehicle) / deleteObject(object) | Deletes the entity |
xLib.game.isVehicleEmpty(vehicle) | true when no ped is inside |
xLib.game.getPeds(onlyOtherPeds?) / getVehicles() / getObjects() | Entity pools |
xLib.game.getPlayers(onlyOtherPlayers?, returnKeyValue?, returnPeds?) | Active players |
xLib.game.getClosestPlayer(coords?) / getClosestPed(coords?, modelFilter?) / getClosestObject(coords?, modelFilter?) / getClosestVehicle(coords?, modelFilter?) | Returns entity, distance |
xLib.game.getPlayersInArea(coords, maxDistance) / getVehiclesInArea(coords, maxDistance) | Entities in a radius |
xLib.game.isSpawnPointClear(coords, maxDistance) | true when no vehicle is in the radius |
xLib.game.getVehicleInDirection() | Vehicle in front of the player |
xLib.game.getVehicleProperties(vehicle) / setVehicleProperties(vehicle, props) | Read and apply vehicle mods, colors, extras |
xLib.game.getPedMugshot(ped, transparent?) | Returns headshot handle and txd string |
xLib.entity.closest(entities, isPlayerEntities, coords?, modelFilter?) | Closest entity and distance |
xLib.entity.EnumerateWithinDistance(entities, isPlayerEntities, coords?, maxDistance) | Entities within distance |
xLib.entity.Teleport(entity, coords, cb?) | Teleports and waits for collision |
The ESX.Game.* client functions in es_extended are direct aliases of these (ESX.Game.SpawnVehicle = xLib.game.spawnVehicle and so on). See ESX.Game.
Server player and OneSync helpers
source may be a number or numeric string. Functions return nil (or false) for invalid or disconnected players instead of erroring.
| Function | Returns |
|---|---|
xLib.player.getPed(source) | Ped or nil |
xLib.player.getCoords(source) | vector3 or nil |
xLib.player.distanceToCoords(source, coords) | Distance or nil |
xLib.player.isNearCoords(source, coords, distance) | nearby, actualDistance |
xLib.player.distanceToPlayer(source, target) | Distance or nil |
xLib.player.isNearPlayer(source, target, distance) | nearby, actualDistance |
xLib.player.findNearbyCoords(source, coordsList, distance) | coords, index, actualDistance |
xLib.player.isNearAnyCoords(source, coordsList, distance) | nearby, index, actualDistance |
xLib.onesync.getPlayersInArea(source, maxDistance, ignore?, routingBucket?) | Players near a player id or vector3 |
xLib.onesync.getClosestPlayer(source, maxDistance, ignore?, routingBucket?) | Closest player |
xLib.onesync.getPedsInArea / getObjectsInArea / getVehiclesInArea(coords, maxDistance, modelFilter?) | Entities in area |
xLib.onesync.getClosestPed / getClosestObject / getClosestVehicle(coords, modelFilter?) | entity, distance, coords |
xLib.server.* (getPlayerCoords, distanceToCoords, isPlayerNearCoords, distanceToPlayer, isPlayerNearPlayer, isPlayerNearAnyCoords) and xLib.validation.playerNearCoords / playerNearPlayer are aliases of the same checks. Use them to validate client requests, for example that a player is actually standing at a shop before you charge them:
local SHOP <const> = vector3(25.7, -1347.3, 29.5)
xLib.callback.register('myshop:buy', function(source, item)
if not xLib.player.isNearCoords(source, SHOP, 5.0) then
return false
end
-- process purchase
return true
end)Validation and type checks
xLib.validation (shared)
| Function | Returns |
|---|---|
xLib.validation.number(value, min?, max?, round?) | Finite number in range, else nil |
xLib.validation.integer(value, min?, max?, mode?) | Integer (mode: round, floor, ceil), else nil |
xLib.validation.count(value, max?) | Positive item count, else nil |
xLib.validation.money(value, min?, max?) | Rounded non-negative amount, else nil |
xLib.validation.string(value, options?) | Trimmed string, else nil. Options: trim, allowEmpty, minLength, maxLength, pattern |
xLib.validation.oneOf(value, values) | true when value is in the array |
xLib.validation.player(source) | Server only. true for a connected player |
RegisterNetEvent('myshop:deposit', function(amount)
local value = xLib.validation.money(amount, 1, 1000000)
if not value then return end
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer and xPlayer.getMoney() >= value then
xPlayer.removeMoney(value, 'Shop deposit')
xPlayer.addAccountMoney('bank', value, 'Shop deposit')
end
end)xLib.verify
local ok = xLib.verify(value, types, throwError)Checks value against one type or an array of types and returns a boolean, or raises an error when throwError is true. Supported types: Lua types plus array, int, uint, float, char, vector3, vector4, ped, vehicle, prop, playerId, class and model. On the server, model asks a random connected client to validate the model through the xLib:validateModel callback. xLib.verify.debug(...) only runs when the xLib:debug convar is true.
Rate limiter and tokens (server)
xLib.rateLimiter
local limiter = xLib.rateLimiter(options)| Option | Type | Description |
|---|---|---|
capacity | number | Max tokens per key |
refill | number | Tokens restored per interval |
interval | number | Interval in ms |
maxEntries | number? | Max tracked keys (convar xLib:rateLimiterMaxEntries, default 4096) |
staleMs | number? | Idle time before a full bucket is pruned |
pruneInterval | number? | Min time between prunes |
Methods: limiter:consume(key, cost?) returns allowed, retryAfterMs; limiter:retryAfter(key, cost?), limiter:reset(key), limiter:clear(), limiter:size(). Buckets keyed by a player id are reset on playerDropped.
local limiter = xLib.rateLimiter({ capacity = 5, refill = 1, interval = 2000 })
RegisterNetEvent('myjob:search', function()
local allowed, retryAfter = limiter:consume(source)
if not allowed then
return TriggerClientEvent('esx:showNotification', source, ('Wait %d s'):format(math.ceil(retryAfter / 1000)), 'error')
end
-- handle search
end)xLib.token
| Function | Description |
|---|---|
xLib.token.create({ source?, ttl, data? }) | Returns a token id. ttl in ms (default 30000). Max entries via xLib:tokenMaxEntries (default 4096). |
xLib.token.consume(id, source?) | Returns data once; the token is deleted. Fails if source does not match. |
xLib.token.remove(id) | Deletes a token |
xLib.token.reset(source) | Deletes all tokens of a player, returns count |
xLib.token.clear() / xLib.token.size() | Clear all / count |
Tokens of a player are removed on playerDropped.
Pub/sub
The server subscribes players to topics and publishes data only to them. Clients can only listen. Topic names must match ^[%w_:%.%-]+$ (max 200 chars); prefix them with your resource name.
| Function | Side | Description |
|---|---|---|
xLib.pubsub.subscribe(src, topic) | Server | Returns true if added |
xLib.pubsub.unsubscribe(src, topic) | Server | Returns true if removed |
xLib.pubsub.publish(topic, data) | Server | Sends to all subscribers, returns the count |
xLib.pubsub.subscribers(topic) | Server | Array of server ids |
xLib.pubsub.isSubscribed(src, topic) | Server | Boolean |
xLib.pubsub.clear(topic) | Server | Drops the topic, returns removed count |
xLib.pubsub.on(topic, handler) | Client | handler(data, topic) |
xLib.pubsub.off(topic, handler?) | Client | Removes one or all handlers |
Players are removed from all topics on disconnect, and topics are cleared when the resource that created them stops.
local TOPIC <const> = 'myshop:247:stock'
RegisterNetEvent('myshop:openShop', function()
xLib.pubsub.subscribe(source, TOPIC)
end)
local function updateStock(stock)
xLib.pubsub.publish(TOPIC, stock)
endShared utilities
Table, string and math
xLib.table: isArray, searchForKey, filter, deepcopy, merge, dump, sizeOf, set, indexOf, lastIndexOf, find, findIndex, map, reverse, clone, concat, join, contains, sort (sorted pairs iterator), toArray, wipe. The ESX.Table.* functions are direct aliases, see ESX.Table.
xLib.string: normalize, capitalize, toSnake, toCamel, toPascal, escapePattern, matchSafe, before, after, contains, replace, randomHex(length), uuid().
xLib.math: clamp, toNumber, tryNumber, toInteger, toScalars, toVector, normalToRotation, toRGBA, hexToRGBA, toHex, groupDigits, round, interpolate, lerp, inverseLerp, remap, plus the ESX-style Round, GroupDigits, Trim, Random, GetHeadingFromCoords used by ESX.Math.
Timeout and waitFor
local id = xLib.timeout.setTimeout(msec, cb)
xLib.timeout.clearTimeout(id)
local value = xLib.waitFor(cb, errMessage, timeout, interval)waitFor calls cb until it returns a non-nil value. It errors after timeout ms (default 5000; pass false to wait forever) and polls every interval ms (default 0). ESX.SetTimeout, ESX.ClearTimeout and ESX.Await are aliases. See Timeout.
local vehicle = xLib.waitFor(function()
local veh = GetVehiclePedIsIn(PlayerPedId(), false)
if veh ~= 0 then return veh end
end, 'Player never entered a vehicle', 10000)Vehicle plates
| Function | Description |
|---|---|
xLib.vehiclePlate.normalize(plate, options?) | Trimmed, normalized plate or nil. Options: maxLength, uppercase, compact, allowEmpty, pattern, coerce |
xLib.vehiclePlate.equals(left, right, options?) | Compares two plates after normalizing |
xLib.vehiclePlate.matchesVehicle(vehicle, plate, options?) | Compares against a vehicle's plate |
xLib.vehiclePlate.generate(options?) | Random plate. Options: prefix, suffix, letters (3), numbers (3), useSpace |
xLib.vehiclePlate.generateUnique(options?, exists?) | Retries up to options.attempts (30) until exists(plate) returns false; reserves the plate for 30 s |
xLib.vehiclePlate.randomLetters(length) / randomNumbers(length) | Random chunks |
Other shared modules
xLib.class(copy?)creates a class; instances are made withClass:new(...), which callsconstructor.xLib.overload(name, validTypes, cb, obj?)registers a typed overload, dispatched by argument types.xLib.isEnhanced()returnstrueon the GTA V Enhanced build (server:gamenameconvargta5enhancedorgta5_enhanced).xLib.colorsexposesbrand,darkest,dark,mid,light,lightestandgetESXTheme(defaults?). See convars.
require, load and loadJson
local config = require 'config.shops' -- loads config/shops.lua from your resource
local other = require '@other_resource.data' -- loads data.lua from another resource
local result = xLib.load('scripts/once') -- runs a file without caching
local data = xLib.loadJson('data/items') -- decodes data/items.jsonDots become slashes. Search paths are ./?.lua and ./?/init.lua. The file must be listed in the target resource's files or scripts so LoadResourceFile can read it on the client. Circular requires raise an error.
Other client modules
xLib.blips.create(data),xLib.blips.createMany(items, defaults?),xLib.blips.remove(blip).datacan be avector3or a table withcoordsorentityorradius, plussprite,display,scale,color,alpha,shortRange,label,route,routeColorand more.xLib.dui:new({ url, width, height, debug? })withremove(),setUrl(url),sendMessage(message),sendMouseMove(x, y),sendMouseDown(button),sendMouseUp(button),sendMouseWheel(deltaX, deltaY). DUIs are destroyed when the resource stops.xLib.scaleform.showFreemodeMessage(title, msg, sec),showBreakingNews(title, msg, bottom, sec),showPopupWarning(title, msg, bottom, sec),showTrafficMovie(sec), plusxLib.scaleform.utils.requestScaleformMovie(movie)andrunMethod(scaleform, methodName, returnValue?, ...).xLib.Raycast.FromScreen(depth, ...),xLib.Raycast.Start(depth, ...),xLib.Raycast:Stop(),xLib.Raycast:IsActive(),xLib.Raycast.GetShapeTestResult(shape).xLib.medal.triggerClip(publicKey?, eventName?, clipOptions?)andxLib.medal.getConfig().
Server-only modules
xLib.schema(needs oxmysql):column(tableName, columnName),identifier(value),ensureColumn(tableName, columnName, definition),widenVarchar(tableName, columnName, length, column?),ensureProperty(),ensureMileage(). es_extended migrations and esx_multicharacter use it to adjust tables safely.xLib.triggerClientEvent(eventName, targets, ...):targetsis one server id or an array. For arrays, the payload is packed once and sent to each client, which is cheaper than callingTriggerClientEventin a loop.
SQL catalog
imports/catalog/bootstrap.lua is loaded as a server script by es_extended, esx_identity, esx_multicharacter and esx_skin. On start it reads imports/catalog/data.json (catalog version 1.16.0) and creates missing tables, columns and seed rows (jobs, items, licenses, vehicles and more) for ESX core and official addons, using the locale from Config.SqlCatalogLocale, Config.Locale or the esx:locale convar. Other resources call the es_extended export EnsureSqlCatalog(name, locale), which only lets a resource prepare its own catalog. When done, it triggers the server event esx:sqlCatalogReady with the list of touched catalogs. If it fails, resource initialization is blocked and the console prints SQL catalog FAILED.
Exports
Functions defined in esx_lib's own resource/ scripts are exported automatically. You normally reach them through xLib, but they are callable as exports.esx_lib:<name>(...):
| Export | Side | Description |
|---|---|---|
setValidCallback(name, isValid, owner?) | Both | Internal callback ownership registry |
isCallbackValid(name) | Both | true if a callback name is registered |
acquireCallbackBudget / releaseCallbackBudget / chargeCallbackBytes | Server | Internal callback rate budget |
pubsub_subscribe, pubsub_unsubscribe, pubsub_publish, pubsub_subscribers, pubsub_isSubscribed, pubsub_clear | Server | Pub/sub registry |
triggerClientEvent(eventName, targets, ...) | Server | Packed multi-target event |
getMedalConfig() / triggerMedalClip(publicKey, eventName, clipOptions) | Client | Medal.tv integration |
Events
| Event | Side | Type | Payload |
|---|---|---|---|
xLib:cache:<key> | Client | Local | value, previous for ped, vehicle, seat, weapon |
xLib:interact | Client | Local | Fired when the esx_interact key is pressed |
xLib:validateCallback | Both | Net (internal) | Callback validation |
esx:sqlCatalogReady | Server | Local | catalogs table, fired by the catalog bootstrap |
Configuration
config.lua only configures the Medal.tv integration. esx_lib's NUI page posts clip requests to the Medal desktop client at http://localhost:12665, so nothing happens for players who do not run Medal.
| Key | Default | Description |
|---|---|---|
Config.Medal.enabled | true | Allow xLib.medal.triggerClip |
Config.Medal.publicKey | ESX public key | Medal API public key |
Config.Medal.eventName | 'Death' | Default event name |
Config.Medal.clipOptions.duration | 30 | Clip length in seconds |
Config.Medal.clipOptions.captureDelayMs | 0 | Delay before capture |
Config.Medal.clipOptions.alertType | 'Default' | Default, Disabled, SoundOnly or OverlayOnly |
Convars
| Convar | Default | Description |
|---|---|---|
xLib:debug | false | Debug output, enables xLib.verify.debug |
xLib:nuiDeferTimeout | 10000 | Deferred NUI callback timeout (ms) |
xLib:streamingTimeout | 10000 | Streaming request timeout (ms) |
xLib:rateLimiterMaxEntries | 4096 | Default max keys per rate limiter |
xLib:tokenMaxEntries | 4096 | Max active tokens |
esx:brand-color | #FB9B04 | xLib.colors.brand |
esx:darkest-color / esx:dark-color / esx:mid-color / esx:light-color / esx:lightest-color | #161616 / #252525 / #383838 / #969696 / #F2F2F2 | Palette |
esx:ui:primaryColor, esx:ui:secondaryColor, esx:ui:backgroundColor, esx:ui:accentColor, esx:ui:logoUrl | palette values | Theme returned by xLib.colors.getESXTheme() |
Callback convars are listed in Callback limits.
setr esx:ui:primaryColor "#3B82F6"
set xLib:callbackTimeout 60000Version reporting
On the server, esx_lib publishes the version and legacyversion metadata of every ESX resource (names starting with esx_ or es_, or that depend on es_extended or esx_lib) as server info convars named <resource>-version. This is what server lists and support tools read to see which ESX version you run. It runs 2 seconds after start and again for each ESX resource that starts later.
Common issues
attempt to index a nil value (global 'xLib'):@esx_lib/imports.luais missing fromshared_scripts, or esx_lib is not started.- Renamed folder: the loader reads files from a resource literally named
esx_lib. Keep the name. callback '<name>' does not exist: the name is not registered on the receiving side, or its resource stopped. On the server this is reported after the validation grace period (up to 15 s).callback '<name>' is already owned by resource '<x>': two resources registered the same callback name. Prefix names with your resource.- Callback returns
falseunder load: the player hit a callback budget. Check the callback limits and avoid calling server callbacks every frame; use the clientdelayargument. requirecannot find a file on the client: the file is not in the resource'sfileslist, soLoadResourceFilecannot read it.SQL catalog FAILED: oxmysql is not connected or the database user cannot create or alter tables.
Related
- ESX Legacy core resources
- Callbacks guide
- ESX shared functions
- Client callback module
- OneSync server functions
Frequently asked questions
Independent documentation
Last updated on
Core Resources
Overview of every ESX Legacy 1.16.4 core resource in [core], what each one does, which are required, and the recommended ensure order for server.cfg.
esx_context
esx_context reference for ESX Legacy. Open mouse-driven context menus and small forms with ESX.OpenContext, element fields, exports, keybind and pitfalls.