Devices/Frameworks

Frameworks

Supported frameworks, inventories and how to add your own bridge.

Devices pages

Evolent Devices talks to your framework through one bridge file per framework on each side, and to optional scripts through integrations. Nothing else calls a framework.

Supported Frameworks

QboxQBCoreESX
Config valueqboxqbcoreesx
Resourceqbx_coreqb-corees_extended
Character idcitizenidcitizenididentifier, with the multichar prefix such as char1:
Offline lookupsGetOfflinePlayer of qbx_corethe players tablethe users table
Jobsjob and grade, plus the extra jobs of Qboxjob and gradejob and grade
On dutyjob.ondutyjob.ondutyjob.onDuty when ESX has it, else on duty
GangsYesYesNo
Admin checkAcesAces, then QBCore permissionsAces, then ESX groups

Config.framework = 'auto' takes the first framework that runs: qbx_core, then qb-core, then es_extended. Character ids are stored with up to 60 characters.

ESX has no gangs: the panel greys out the gang line and marks old gang lines, saving a new gang rule is refused and an old one lets nobody in.

Down and restrained

Qbox reads isdead, inlaststand and ishandcuffed of the player metadata and the isDead state bag; QBCore the same metadata. ESX keeps no dead or cuffed state on the server: the client stops device use from esx:onPlayerDeath until esx:onPlayerSpawn and while the ped is cuffed or the isDead or handcuffed state bag is set.

Events

Loaded, logged out and job or gang changes come from QBCore:Server:PlayerLoaded, QBCore:Server:OnPlayerUnload, QBCore:Server:OnJobUpdate, QBCore:Server:OnGangUpdate and QBCore:Server:SetDuty (Qbox and QBCore, Qbox also its own group events) and esx:playerLoaded, esx:playerLogout and esx:setJob (ESX), all as server-only events. When another script makes one of them a network event, a player who fires it can only name themselves.

What a bridge answers about a player (job, gang, duty, home, down) is kept for up to a second and read again at once after one of the events above.

Integrations

FileScriptWhat it does
integrations/server/inventory.luaox_inventory, qb-inventory, ESX inventoryPicks the inventory: ox_inventory when it runs, else qb-inventory on QBCore or the ESX inventory on ESX. Without any of them players get no device items; everything else works.
integrations/server/properties.luaqbx_propertiesThe "people with keys to this home" rule and homes only placing. Qbox only. Owners and key holders are cached for 30 s.
integrations/client/target.luaox_targetUse, In use and Manage on the device. Without it, or with useTarget = false, a key prompt shows instead.
integrations/*/weather.luarenewed-weathersync, qb-weathersync, cd_easytimeThe 3D studio holds the weather and time for its user only. With another weather script, change both files.
integrations/client/hud.luaYour HUDHides the HUD while a device is in use: it sends qbx_hud:client:setHidden and evolent:client:hudHidden. Point it at your own HUD.

qb-houses, ps-housing and the ESX property scripts are not supported for the home rules; devices placed in their interiors still keep to the routing bucket.

Adding a framework

Each side has one file per framework: bridge/server/qbox.lua, qbcore.lua and esx.lua, and the same names in bridge/client/, plus bridge/server/common.lua for what they share (the aces, the group lists, ox_lib notices). bridge/init.lua lists the functions every bridge must have in Bridge.contract, and the resource stops at start when one is missing.

Write the bridge

Copy the bridge closest to your framework, give it a new name and fill in the same functions. Each file sets its functions on the shared bridge table and steps aside unless its framework is the one in use:

bridge/server/myframework.lua
local Bridge = require 'bridge'

if not Bridge.uses('myframework') then return end

function Bridge.getCharacterId(source)
    -- return the character id of the player
end

Let the bridge be found

Add your framework to Bridge.FRAMEWORKS in bridge/init.lua, with the resource that marks it:

bridge/init.lua
Bridge.FRAMEWORKS = {
    { id = 'qbox', resource = 'qbx_core', label = 'Qbox' },
    { id = 'qbcore', resource = 'qb-core', label = 'QBCore' },
    { id = 'esx', resource = 'es_extended', label = 'ESX' },
    { id = 'myframework', resource = 'my_core', label = 'My framework' }, 
}

Load it

The resource loads its files with require from one entry script per side. Add your files to server/init.lua and client/init.lua next to the other bridges:

server/init.lua
require 'bridge.server.esx'
require 'bridge.server.myframework' 

Integrations work the same way: their functions are set on require 'integrations', and Integrations.contract in integrations/init.lua lists the ones the server needs.