The resources every server uses
FiveM gives you the game engine; a roleplay framework adds money, jobs, inventory and persistent identity. Here you'll see ESX, QBCore and the ox ecosystem, and discover the concepts are the same across all of them.
FiveM on its own gives you an empty GTA V server: the engine, the network and the ability to load resources. But it doesn't know what «money» is, nor a «job», nor an «inventory», nor who you are from one session to the next. All of that comes from a roleplay framework: a base of resources installed on top of FiveM that defines the rules of the roleplay game.
What a roleplay framework is
A framework is the layer that turns an empty server into an RP server. It gives you the common pieces almost any server needs, so you don't have to reinvent them in every resource.
- Persistent identity: each player has a character saved in the database (name, appearance, data).
- Money: cash, bank and, sometimes, dirty money, with functions to add and subtract.
- Jobs: police, mechanic, taxi driver... with ranks and permissions.
- Inventory: items the player carries and that are saved on disconnect.
Remember it this way: FiveM is the car engine; the framework is the car built around it. The two most used frameworks in the Spanish-speaking world are ESX and QBCore.
ESX Legacy (es_extended)
ESX is the most veteran framework and the one with the most third-party resources available. Its main resource is called es_extended. To use it from your script you get the «shared object» (the ESX core) and, from it, you access the players.
-- Get the ESX core (server side)
ESX = exports['es_extended']:getSharedObject()
RegisterCommand('pay', function(source)
local xPlayer = ESX.GetPlayerFromId(source) -- the player object
if not xPlayer then return end
xPlayer.addMoney(500) -- give them 500 in cash
print(xPlayer.getMoney()) -- how much cash they have
print(xPlayer.job.name) -- their current job, e.g. 'police'
end)
-- Callback: the client asks, the server answers
ESX.RegisterServerCallback('my_resource:balance', function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
cb(xPlayer.getMoney())
end)The essentials of ESX
QBCore (qb-core)
QBCore is more modern and modular, with a very active community. Its main resource is called qb-core. The idea is identical to ESX: you get the core and from it you access each player; only the function names change.
-- Get the QBCore core (server side)
local QBCore = exports['qb-core']:GetCoreObject()
RegisterCommand('pay', function(source)
local Player = QBCore.Functions.GetPlayer(source) -- the player object
if not Player then return end
Player.Functions.AddMoney('cash', 500) -- give them 500 in cash
print(Player.PlayerData.job.name) -- their job, e.g. 'police'
end)
-- Callback: the client asks, the server answers
QBCore.Functions.CreateCallback('my_resource:balance', function(source, cb)
local Player = QBCore.Functions.GetPlayer(source)
cb(Player.PlayerData.money.cash)
end)The essentials of QBCore
ESX and QBCore, side by side
When you see the two together, you discover it's the same logic with a different vocabulary. This mental table will help you translate any resource from one framework to the other:
- Get the core: ESX.getSharedObject() ↔ QBCore:GetCoreObject()
- Get the player: ESX.GetPlayerFromId(source) ↔ QBCore.Functions.GetPlayer(source)
- Give money: xPlayer.addMoney(500) ↔ Player.Functions.AddMoney('cash', 500)
- Check the job: xPlayer.job.name ↔ Player.PlayerData.job.name
- Create a callback: ESX.RegisterServerCallback(...) ↔ QBCore.Functions.CreateCallback(...)
The ox ecosystem (overextended)
On top of the framework there's a set of resources from the overextended team (the «ox») that have become the modern standard. The good thing is they work with both ESX and QBCore, so learning them serves you in both worlds.
- oxmysql: the connection to the MySQL/MariaDB database. Almost the entire ecosystem depends on it.
- ox_lib: a toolbox (menus, inputs, notifications, zones, callbacks). It saves you writing UI and utilities by hand.
- ox_inventory: a complete inventory, with weight, slots and items saved in the database.
- ox_target: «look-based» interaction: you aim at something and a menu of contextual actions appears.
Bridges: one resource, multiple frameworks
Many modern resources want to be sold or used on both ESX and QBCore. To avoid writing the code twice they use a «bridge»: they detect which framework is active on the server and, from there, call the right functions behind a common interface.
-- Simplified bridge pattern
local Framework, name
if GetResourceState('es_extended') == 'started' then
Framework = exports['es_extended']:getSharedObject()
name = 'esx'
elseif GetResourceState('qb-core') == 'started' then
Framework = exports['qb-core']:GetCoreObject()
name = 'qb'
end
-- Unified function: the rest of the resource no longer cares about the framework
local function giveMoney(src, amount)
if name == 'esx' then
Framework.GetPlayerFromId(src).addMoney(amount)
elseif name == 'qb' then
Framework.Functions.GetPlayer(src).Functions.AddMoney('cash', amount)
end
endHow a bridge supports both frameworks
ESX or QBCore: how to choose
There's no single answer, and both are serious, maintained options. ESX has the largest resource base on the market, so it's easy to find (or buy) almost any system already made. QBCore is usually considered somewhat more modern and modular in its design, with very structured player data. To start out, pick the one used by the community or content creator you follow, because you'll have more examples at hand.
What matters isn't the framework, it's the CONCEPTS: they're the same in both. Learn to get the core, pull out the player, move their money and make callbacks, and you'll be able to work in either one.
The framework changes the names, not the logic. If you master the client-server separation and security (always validate on the server, don't trust the client), you'll move with ease in both ESX and QBCore.
Put it into practice
Got a question about this? The AI chat knows all of it and answers with code.
Ask the AI