Skip to main content

Framework Compatibility

F5 Redeem Code runs on a self-detecting bridge. At startup it resolves a framework and an inventory, wires up money accounts, and picks a notification backend — all from F5Cfg.Framework and F5Cfg.Inventory.

If detection fails, the resource logs an error and goes inert (commands still register, but redeeming/admin do nothing) rather than throwing.

Frameworks​

config/config.lua
F5Cfg.Framework = { mode = 'auto' }   -- 'auto' | 'esx' | 'qb' | 'qbx' | 'custom'

With mode = 'auto', the first started resource wins, in this priority:

PriorityFrameworkDetected resource
1QBox Coreqbx_core
2QBCoreqb-core
3ESXes_extended

Force a specific adapter by setting mode to 'esx', 'qb' or 'qbx', or 'custom' for a fork (see Custom framework).

Inventories​

config/config.lua
F5Cfg.Framework = { inventory = 'auto' }

With inventory = 'auto', detection runs in this priority:

PriorityInventoryDetected resourceItem image path (nui://…)
1ox_inventoryox_inventoryox_inventory/web/images/%s.png
2qs-inventoryqs-inventoryqs-inventory/html/images/%s.png
3ps-inventoryps-inventoryps-inventory/html/images/%s.png
4codem-inventorycodem-inventorycodem-inventory/html/itemimages/%s.png
5tgiann-inventorytgiann-inventoryinventory_images/images/%s.webp
6qb-inventoryqb-inventoryqb-inventory/html/images/%s.png
7ESX native(fallback when framework is ESX)(no image path)

Force one with inventory = 'ox' | 'qb' | 'qs' | 'ps' | 'codem' | 'tgiann' | 'esx_native' | 'custom'.

The image path is used to render item icons in the redeem result and the admin console. Override it globally with:

config/config.lua
F5Cfg.Inventory = {
imageUrl = 'auto', -- or 'nui://my-inventory/images/%s.png'
}

%s is replaced with the item name. Leave it 'auto' to use the detected inventory's path.

Money & Currencies​

Each entry in F5Cfg.Money.types maps an internal id to a native account key per framework:

config/config.lua
{ id = 'cash', label = 'Cash', icon = 'fa-solid fa-money-bill-wave', accounts = { qb = 'cash', qbx = 'cash', esx = 'money' } },

Default active accounts per framework:

Currency idQBCoreQBoxESX
cashcashcashmoney
bankbankbankbank
cryptocryptocrypto—
blackmoney——black_money

Rules the bridge applies at startup:

  • A type with no account for the running framework is skipped (e.g. crypto on ESX, blackmoney on QB/QBox).
  • Type ids must be alphanumeric + _/-, and account keys must be alphanumeric, or the type is dropped with a debug warning.
  • payoutType must resolve to an active type; if not, it falls back to bank, then to the first active type.

The active list is exactly what admins see as per-account money inputs when creating a code, and codes can pay several of them in a single redeem. See Features → Money.

Notifications​

config/config.lua
F5Cfg.Framework = {
notify = 'auto', -- 'auto' | 'framework' | 'oxlib'
notifyStyle = 'custom', -- 'custom' | 'native'
}
OptionValueBehaviour
notify'auto'Use ox_lib notifications when it's present, otherwise the framework's native notify
notify'framework'Always use the framework's native notify
notify'oxlib'Always use ox_lib
notifyStyle'custom'Show this resource's styled in-NUI toasts (the notify backend is not used for these)
notifyStyle'native'Hand messages to the notify backend instead of the NUI toasts

Custom framework​

For a fork of QB / QBox / ESX, set mode = 'custom' and describe only what your fork renamed. Any field left nil inherits the base behaviour — most forks need just base + getCore.

config/config.lua
F5Cfg.Framework = {
mode = 'custom',
custom = {
base = 'qb', -- REQUIRED: 'qb' | 'qbx' | 'esx'
getCore = nil, -- function() return exports['my-core']:GetCoreObject() end

playerLoadedEvent = nil, -- renamed load event (same args as base)
playerUnloadEvent = nil, -- renamed unload event
-- ... advanced overrides below
},
}
FieldPurpose
baseRequired. The framework your fork derives from — 'qb', 'qbx' or 'esx'. Invalid/missing → resource inert
getCoreReturns your core object
playerLoadedEvent / playerUnloadEventRenamed load/unload events (same args as the base)
normalize(raw)Normalize a raw player object
getPlayer(src) / getPlayerByUid(uid) / getPlayers()Player lookups
identifierOf(raw)Extract the Citizen ID from a raw player
getAccount(raw,key) / addAccount(raw,key,amt,reason) / removeAccount(raw,key,amt,reason)Money account access
hasGroup(src,group)Admin group check
onPlayerLoaded(emit) / onPlayerUnload(emit)Custom load/unload wiring — call emit(src, uid) when the args differ from the base
playersTable / uidColumnDB table + column holding Citizen IDs, for private-code target validation. Defaults from base: QB/QBox → players.citizenid, ESX → users.identifier
notify(msg,kind,duration)Client notify override
getPlayerData()Client player data → { uid, name, charinfo, job, raw }

Custom inventory​

Set Framework.inventory = 'custom' and provide every callback. Any callback left nil logs an error and that feature degrades.

config/config.lua
F5Cfg.Inventory = {
custom = {
-- addItem(src,name,amount,metadata) removeItem(src,name,amount,slot)
-- hasItem(src,name,amount) canCarryItem(src,name,amount)
-- getItemLabel(name) getItemImage(name)
-- getAllItems() -> { { name = ..., label = ... }, ... }
},
}
CallbackPurpose
addItem(src, name, amount, metadata)Give an item — used when granting item rewards
removeItem(src, name, amount, slot)Remove an item
hasItem(src, name, amount)Check possession
canCarryItem(src, name, amount)Inventory-space pre-check before granting
getItemLabel(name)Human label for display
getItemImage(name)Icon path for display
getAllItems()Full item catalogue for the admin item picker

Database schema​

The script uses two InnoDB tables (utf8mb4), created and migrated automatically when autoCreateTables is true:

f5_codes​

Holds every code. Key columns:

ColumnNotes
codeThe code string
reward_typeENUM('money','item','both')
moneyLegacy single money amount
moneysJSON — multi-account money list
itemsJSON — item list
max_uses / usesUsage cap and current count
expiryDATETIME, nullable
is_private0 public / 1 private
target_citizenid / target_citizenidsLegacy single target / JSON multi-target list
created_by / creator_name / creator_steamWho created the code
deletedSoft-delete flag
code_activeGenerated column = code while live, NULL when deleted

The unique key uk_code_active is on code_active, so only live codes must have unique names — a deleted code frees its name for re-creation. This generated column needs MySQL 5.7+ / MariaDB 10.2+; on older servers the migration is skipped and the legacy uk_code unique key is kept.

f5_code_redemptions​

One row per successful redemption — code_id, code, citizenid, steam, player_name, money, moneys (JSON), items (JSON) and redeemed_at. This is the source of the once-per-player rule and the admin History tab.

See Also​