Frameworks and custom cores
The framework layer is built in (bridge/). It is detected once, when the resource starts:
| Running | Mode | Setup |
|---|---|---|
qbx_core | Qbox | INSTALLATION.md → Qbox |
qb-core | QBCore | INSTALLATION.md → QBCore |
es_extended | ESX | INSTALLATION.md → ESX |
| none | Standalone | Standalone |
| your own core | Custom | this page |
Qbox wins over QBCore because qbx_core also provides qb-core. To force a mode, set Framework in bridge/config.lua ('qbx', 'qb', 'esx', 'standalone' or 'custom').
Start order matters: your core must be ensured before this resource. If it is installed but starts later, the console names it in a warning and the resource would otherwise run standalone.
Custom core
Set Framework = 'custom' in bridge/config.lua and fill in LumoBridgeConfig.Custom. This is integration work for a developer, not a config switch. Missing required hooks are listed in the console at start; set Debug = true to see every unimplemented call.
Server hooks — Custom.server
| Hook | Signature | Must do |
|---|---|---|
getCharacters | (src) → list | Characters owned by this player, in the shape below. Used to authorise login and delete. |
getPlayer | (src) → object | Your core's player handle. |
getPlayerData | (src) → table | Logged-in character, shape below. Most important hook. |
login | (src, id, newData) → boolean | id set: load it. id nil: create from newData.charinfo (slot newData.cid) and load. true once loaded. |
logout | (src) | Unload without dropping the player. |
deleteCharacter | (src, id) → boolean | Delete the character (ownership is already checked). |
hasPermission | (src, groups) → boolean | True if in any group. Gates /spawneditor. |
notify | (src, message, type) | Your notifications. |
addCommand | (name, help, args, restricted, cb, perm) | Optional; defaults to RegisterCommand + hasPermission. |
addItem, getStarterItems, getSharedItem | Optional starter items. | |
normaliseCharacter | (row) → table | Only if you use the built-in character query. |
Client hooks — Custom.client
| Hook | Signature | Must do |
|---|---|---|
getPlayerData | () → table | Same shape, local player. |
isLoggedIn | () → boolean | |
notify | (message, type, duration) | |
announceLoaded | () | Fire your "player is in the world" events. |
frameworkCallback | (name, cb, ...) | Only for callbacks owned by other resources (apartments, houses). |
Character shape
lua
{
citizenid = 'ABC12345', -- unique string
cid = 1, -- slot 1..N
charinfo = { firstname = 'Ana', lastname = 'Rai', birthdate = '1998-01-02',
gender = 0, nationality = 'Nepali', phone = '', account = '' },
money = { cash = 0, bank = 0 },
job = { name = 'unemployed', label = 'Unemployed', grade = { name = '', level = 0 } },
gang = { name = 'none', label = 'No Gang', grade = { name = 'none', level = 0 } },
position = { x = 0.0, y = 0.0, z = 0.0, w = 0.0 }, -- or nil
metadata = {},
}citizenid, cid and charinfo must be right; the rest degrade gracefully.
Different table names
If your characters are not in players / citizenid, set the schema from a file you add after bridge/server/db.lua in the manifest:
lua
LumoBridge.Db.Schema = { table = 'my_characters', id = 'char_id', license = 'owner',
slot = 'slot', skinTable = 'my_skins', skinId = 'char_id' }bridge/server/adapters/esx.lua is the best reference: a different schema and a different login flow mapped onto the same contract.