Перейти к содержимому
Exports and dependencies

Exports and dependencies

Share code between FiveM resources with exports, call framework functions, declare dependencies in fxmanifest, import @resource files and bridge frameworks.

Эта документация пока на английском.

Last updated

Resources are isolated from each other: a global variable in one resource doesn’t exist in another. To share functionality you use exports (call a function in another resource) and shared files (load another resource’s file into yours with @resource/path). Dependencies make sure the resource you rely on is there and starts first.

Plays from youtube-nocookie.com after you click.

Exports

Defining an export

banking/server.lua
local accounts = {}

exports('getBalance', function(identifier)
    return accounts[identifier] or 0
end)

exports('addBalance', function(identifier, amount)
    if type(amount) ~= 'number' or amount <= 0 then return false end
    accounts[identifier] = (accounts[identifier] or 0) + amount
    return true
end)

exports(name, fn) works in Lua without any manifest entry. Exports are per side: a server export is only callable from server scripts, a client export only from client scripts.

Calling an export

another_resource/server.lua
local balance = exports.banking:getBalance(identifier)
exports['banking']:addBalance(identifier, 500)

Use the bracket form when the resource name has a dash: exports['qb-core']:GetCoreObject(). Note the colon: exports are called like methods.

If the resource isn’t started, the call errors with No such export getBalance in resource banking. Guard with GetResourceState('banking') == 'started' if it’s optional.

JavaScript and C#

JavaScript
exports('getBalance', (identifier) => accounts[identifier] ?? 0);
const balance = exports.banking.getBalance(identifier);

C# resources call them through Exports["banking"].getBalance(identifier).

Using a framework through exports

Frameworks expose their core object or functions as exports:

Lua
-- QBCore
local QBCore = exports['qb-core']:GetCoreObject()
local Player = QBCore.Functions.GetPlayer(source)

-- Qbox
local player = exports.qbx_core:GetPlayer(source)
exports.qbx_core:AddMoney(source, 'cash', 100, 'fishing')

-- ESX Legacy
local ESX = exports['es_extended']:getSharedObject()
local xPlayer = ESX.GetPlayerFromId(source)

-- ox_inventory
exports.ox_inventory:AddItem(source, 'water', 1)

See the Frameworks pages for more.

Importing files with @resource

A manifest can load another resource’s file as if it were yours:

fxmanifest.lua
shared_script '@ox_lib/init.lua'
server_script '@oxmysql/lib/MySQL.lua'
  • @ox_lib/init.lua sets up the lib global and cache in your resource.
  • @oxmysql/lib/MySQL.lua gives you the MySQL global.
  • @qbx_core/modules/lib.lua and @qbx_core/modules/playerdata.lua are Qbox helpers.
  • @es_extended/imports.lua sets up ESX in your resource.

The file runs inside your resource’s environment, so this is faster than calling an export for every small helper. The other resource must be present (and for ox_lib, started first).

Dependencies

List what your resource needs in the manifest:

fxmanifest.lua
dependencies {
    'oxmysql',
    'ox_lib',
    '/onesync',             -- requires OneSync
    '/server:12913',        -- requires at least this server artifact
    '/gameBuild:3095',      -- requires at least this game build (name like 'h4' works too)
}

FXServer then:

  • starts listed resources before yours, and refuses to start yours if one is missing,
  • refuses to start it if the server or game requirements aren’t met, with a clear error.

This is much more reliable than hoping ensure order in server.cfg is right. The /server:, /onesync, /gameBuild:, /policy: and /native: forms come from the official manifest reference. The build numbers above are just examples: use the ones your resource really needs.

provide: replacing another resource

fxmanifest.lua
provide 'mysql-async'

Tells FXServer this resource satisfies dependencies on mysql-async. oxmysql uses it so old resources that depend on mysql-async or ghmattimysql keep working. Only use provide if you really implement the same API.

Writing framework independent resources

If you want your resource to work on QBCore, Qbox and ESX, don’t sprinkle framework calls everywhere. Put them behind a small bridge:

bridge/server.lua
Bridge = {}

local function detect()
    if GetResourceState('qbx_core') == 'started' then return 'qbx' end
    if GetResourceState('qb-core') == 'started' then return 'qb' end
    if GetResourceState('es_extended') == 'started' then return 'esx' end
    return 'standalone'
end

local fw = detect()
local QBCore = fw == 'qb' and exports['qb-core']:GetCoreObject() or nil
local ESX = fw == 'esx' and exports['es_extended']:getSharedObject() or nil

function Bridge.addMoney(src, amount)
    if fw == 'qbx' then
        return exports.qbx_core:AddMoney(src, 'cash', amount)
    elseif fw == 'qb' then
        local p = QBCore.Functions.GetPlayer(src)
        return p and p.Functions.AddMoney('cash', amount)
    elseif fw == 'esx' then
        local x = ESX.GetPlayerFromId(src)
        if x then x.addMoney(amount) return true end
    end
    return false
end

The rest of your code calls Bridge.addMoney(src, 100) and never cares which framework runs. Paid resources on Tebex use exactly this pattern, often leaving the bridge files open under escrow_ignore. (Qbox also ships QBCore compatibility, so many qb-core calls work on Qbox too.)

Load order inside a resource

  • shared_scripts load first, on both sides.
  • Then client_scripts (client) or server_scripts (server), in the order listed.
  • Globs (client/*.lua) load in alphabetical order.

So put config.lua and library imports at the top of shared_scripts.

Common mistakes

  • No such export: wrong resource name (check the folder name), resource not started, calling a server export from the client (or the reverse), or the export was renamed in a new version.
  • attempt to index a nil value (global 'lib'): you forgot shared_script '@ox_lib/init.lua'.
  • Circular dependencies: A depends on B and B on A. Move shared code into a third resource.
  • Exporting huge tables every call: exports copy data between resources. Return what’s needed.

Next: Debugging.