Skip to content

Installation — lumo-inventory ​

Pick your framework below and follow only that section, then do the common steps and the test checklist.

Back up first. Copy your database and the inventory resource you are replacing somewhere safe. Rolling back is then just moving a folder back.

The download contains:

lumo-inventory/                  the inventory (this is the resource you ensure)
[compat]/qb-inventory/           name shim: needed on QBCore
[compat]/ox_inventory/           name shim: needed on Qbox

Move the shim your framework needs into place (steps below) and delete the rest of [compat]; do not copy the whole folder into your server. Each shim contains no inventory logic, only forwarders. Never keep one next to the real resource of that name, or a second copy of a shim anywhere.

What to stop and what to keep ​

lumo-inventory replaces the inventory only. Shops, weapon shops and licences stay with the scripts your framework already uses, except on Qbox, where the shops came from ox_inventory and now come from the shim.

StopKeepShops come from
QBCoreqb-inventory (replaced by the [compat]/qb-inventory shim)qb-shops, qb-weapons (optional), qb-targetqb-shops: its licence, job and grade rules are checked here on every purchase
Qboxthe real ox_inventory (replaced by the [compat]/ox_inventory shim)ox_lib, ox_target, every qbx scriptThe shim's data/shops.lua: ~45 shops ship with it. No other shop script needed
ESXesx_inventory (F2 menu), esx_inventoryhud, any other inventoryesx_shops, esx_weaponshop, esx_license, esx_addoninventoryesx_shops (set Config.Inventory = 'esx') and esx_weaponshop (needs esx_license)
Standaloneany other inventory—Your own script, through CreateShop / OpenShop

Weapons: no extra weapon script is needed anywhere. On QBCore qb-weapons is used when it runs; everywhere else the built-in handler equips weapons, loads ammo and fits attachments and tints.


QBCore ​

qb-core loads and saves player items through exports['qb-inventory'], so the inventory takes over that name with the shim.

  1. Copy lumo-inventory into resources/ (any category, e.g. [lumo]).
  2. Remove the real qb-inventory: move its folder out of [qb] into a category nothing starts (see Disabling a resource).
  3. Move [compat]/qb-inventory to resources/[qb]/qb-inventory (where the old one was), and delete the rest of [compat].
  4. server.cfg:
    cfg
    ensure oxmysql
    ensure qb-core
    ensure lumo-inventory
    ensure [qb]                # includes the qb-inventory shim, qb-weapons, qb-target …
    The shim depends on lumo-inventory, so FiveM starts lumo-inventory first even if [qb] comes earlier.
  5. Restart. Console:
    [lumo-inventory] player items are stored in `players`.`inventory`
    [lumo-inventory] ready — framework: qb, version 1.0.0

Notes:

  • Items stay where qb-core keeps them (players.inventory); stashes, trunks and gloveboxes use qb-inventory's inventories table. Nothing to migrate.
  • Weapons: qb-weapons keeps equipping weapons, loading ammo and fitting attachments as before. Without qb-weapons the built-in handler takes over.
  • Item pictures: html/images/<image> where <image> is the item's image in qb-core/shared/items.lua. Copy the pictures of your own items there.
  • Cash as an item: only if your qb-core has it (QBConfig.Money.UseCashAsItem), set Config.Money.useCashAsItem = true.

Qbox (qbx_core) ​

qbx_core refuses to start unless a resource named ox_inventory exists, and Qbox scripts call ox_inventory's exports. The [compat]/ox_inventory shim answers both.

  1. Copy lumo-inventory into resources/.
  2. Remove the real ox_inventory: move it out of [ox] into a category nothing starts. Do not leave a second copy anywhere (FiveM would warn "ox_inventory exists in more than one place" and pick one).
  3. Move [compat]/ox_inventory to resources/ox_inventory, and delete the rest of [compat].
  4. Your items and shops. The shim ships data/items.lua and data/weapons.lua made from the built-in item list, and data/shops.lua with about 45 ready shops: 24/7 stores, liquor stores, hardware, Ammu-Nation and the job armouries (police, EMS, mechanics). To keep your Qbox item list (ox names such as water, burger), copy your old ox_inventory/data/items.lua, weapons.lua and shops.lua over them, and your old item pictures (ox_inventory/web/images/*.png) into lumo-inventory/html/images/. Keep the Weapons, Ammo and Components keys in weapons.lua even if empty; qbx_core reads all three. Every weapon in weapons.lua becomes a usable weapon item on its own (lower case, e.g. weapon_pistol); you do not have to list weapons in items.lua.
  5. server.cfg, the inventory before [ox] and [qbx]:
    cfg
    ensure ox_lib
    ensure oxmysql
    ensure qbx_core
    ensure ox_target
    
    ensure lumo-inventory
    ensure ox_inventory        # the shim
    
    ensure [ox]
    ensure [qbx]
    Keep setr inventory:framework "qbx" in your config; qbx_core reads it.
  6. Restart. Console:
    [lumo-inventory] player items are stored in `lumo_inventories`.`items`
    [lumo-inventory] ready — framework: qbx, version 1.0.0
    qbx_core requires version '2.42.1' of 'ox_inventory' means the real ox_inventory is still the one being loaded.

How items are used on Qbox. Using an item goes, in order, to:

  1. Weapons: drawn by the built-in weapon handler (no qb-weapons on Qbox).
  2. Food and drink: Config.Consumables in config/config.lua, or, for anything not listed there, the item's own ox client.status in items.lua (status = { hunger = 200000 } fills 20 % of the bar, as on ox_inventory).
  3. Everything else: a handler a script registered with exports.qbx_core:CreateUseableItem(name, fn) (or exports['lumo-inventory']:CreateUsableItem).

An item that matches none of these shows "This item could not be used". ox item fields that only real ox_inventory runs (client.export, server.export, client.event) are not called: register the item with CreateUseableItem in the script that owns it instead.

Notes:

  • Player items are stored in lumo_inventories (created on first start). Qbox's players.inventory column belongs to ox_inventory's format and is never touched, so moving back is just swapping the folders again.
  • ox hooks (registerHook): openInventory fires, so qbx_properties' stash permissions are enforced. Other hook events are accepted but never fire, so a script that uses one to block an action cannot block it. Client-side ox exports are partly covered. If a script reports a missing ox export, send us its name.
  • Shops use ox_inventory's data/shops.lua format, and the rules in it are enforced: groups (only those jobs/gangs can open the shop), license on an item (needs that licence in the character's metadata.licences, e.g. the weapon licence for guns) and grade (minimum job grade). Scripts that add shops with exports.ox_inventory:RegisterShop work the same way. Each shop location gets a blip and an ox_target / qb-target zone.
  • Weapons and ammo use the built-in handler. Ox ammo items are named ammo-9 etc.: add them to Config.Weapons.Ammo if you kept ox's item list, e.g. ['ammo-9'] = { type = 'AMMO_PISTOL', amount = 12 }.

ESX (es_extended) ​

Needs ESX Legacy 1.9 or newer (it uses ESX's inventory override hook, the same one ox_inventory uses).

  1. Copy lumo-inventory into resources/.

  2. Stop the ESX inventory screens, keep the storage:

    ResourceWhat it isDo
    esx_inventory (in [core] on recent ESX Legacy, e.g. 1.15)ESX's old F2 item menuStop it: move it out of [core] (e.g. into a disabled folder) or remove its ensure
    esx_inventoryhud, ox_inventory, any other inventoryA second inventoryStop it
    esx_addoninventoryJob and property storage (police armory, property chest …) used by esx_society, esx_policejob, esx_property …Keep it. Those scripts break without it
    es_extendedThe coreKeep. Its inventory functions are taken over automatically

    Do not install the ox_inventory shim on ESX: ESX would switch to its ox mode. Leave Config.CustomInventory = false in es_extended's config.

  3. server.cfg:

    cfg
    ensure oxmysql
    ensure ox_lib              # recommended: progress bars and prompts
    ensure es_extended
    ensure lumo-inventory
    ensure [esx_addons]        # your ESX scripts, after the inventory
  4. Restart the server (not just the resource). Console:

    [lumo-inventory] player items are stored in `lumo_inventories`.`items`
    [lumo-inventory] ESX inventory functions (xPlayer.addInventoryItem …) now use lumo-inventory
    [lumo-inventory] ready — framework: esx, version 1.0.0

What happens on ESX:

  • ESX scripts keep working. xPlayer.addInventoryItem, removeInventoryItem, getInventoryItem, canCarryItem, canSwapItem, setInventoryItem, hasItem, getWeight, addWeapon, removeWeapon, hasWeapon, addWeaponAmmo … all go to lumo-inventory. Shops, jobs and drug scripts pay out into it unchanged.

  • Existing players keep their things. The first time each character logs in, their ESX items (users.inventory) and weapons (users.loadout) are copied in, once. ESX's columns are left as they were. Turn off with Config.ESX.ImportESXInventory = false.

  • Items come from ESX's items table (label and weight). Pictures, descriptions and weapon data are filled in from the built-in list. ESX weighs in kilograms and this inventory in grams: Config.ESX.ItemWeightScale = 1000 converts (bread 1 = 1000 g). Give ESX-only items a picture by saving html/images/<itemname>.png.

  • Weapons are items. xPlayer.addWeapon('WEAPON_PISTOL', 50) gives a weapon_pistol item with 50 rounds; ESX's own loadout stays empty. The built-in handler equips them, loads ammo items (pistol_ammo …) and saves ammo per weapon.

  • Usable items registered with ESX.RegisterUsableItem work from the inventory. Food and drink listed in Config.Consumables are handled by the inventory itself and feed esx_status (hunger/thirst).

  • Money stays in ESX accounts: cash maps to money, bank to bank.

  • Job and property storage (esx_addoninventory) keeps working and still opens in ESX's own menus. Putting items in and taking them out goes through xPlayer.addInventoryItem / removeInventoryItem, so it moves the player's lumo-inventory items.

  • ESX's own item lists stay up to date. Scripts that read xPlayer.inventory (server) or ESX.PlayerData.inventory (client) instead of calling a function, such as esx_policejob's deposit menu, get the player's current items after every change.

  • Shops (esx_shops). ESX Legacy's esx_shops ships set to ox_inventory. Open esx_shops/shared/config/main.lua and set Config.Inventory = 'esx', so purchases go through xPlayer.addInventoryItem into this inventory. Its own shop screen stays. The inventory reads esx_shops' own config (shared/config/shops.lua): every item a shop sells is known even when it is missing from ESX's items table (shop label, Config.ESX.ShopItemWeight grams), and shows esx_shops' picture (nui://esx_shops/web/images/…). Other shop resources with the same config layout: add them to Config.ESX.ShopResources. Tested against ESX Legacy 1.15.2.

  • Weapon shops (esx_weaponshop) work as they are: weapons arrive as items, and upgrades (attachments and tints) are stored on the weapon item and fitted when it is drawn (straight away if it is already in hand). Right-click the weapon → Attachments lists every part ESX's weapon list allows for it; a bought upgrade taken off there stays with the weapon and can be refitted for free. Its licence check needs esx_license running: without it, pressing E at a gun shop does nothing. Start esx_license, or set Config.LicenseEnable = false in esx_weaponshop/shared/config/main.lua.

  • [E] works at only one of esx_shops / esx_weaponshop (whichever started last; restart esx_shops "fixes" the 24/7 and breaks the gun shop). A bug in esx_lib (1.15.2): every resource that uses xLib.interactions registers the same +esx_interact key command, and a command belongs to one resource only. Fix it once in [core]/esx_lib/imports/interactions/client.lua: replace everything from function xLib.interactions.getInteractKey() down to the xLib.addKeybind({ … }) block's closing }) with

    lua
    -- One key command per resource: a shared name belongs to whichever resource
    -- registered it last, and every other resource's [E] did nothing.
    local keybindName = ("esx_interact_%s"):format(GetCurrentResourceName())
    
    ---@return string
    function xLib.interactions.getInteractKey()
        local hash = joaat("+" .. keybindName) | 0x80000000
        return GetControlInstructionalButton(0, hash, true):sub(3)
    end
    
    xLib.addKeybind({
        name = keybindName,
        description = ("Interact (%s)"):format(GetCurrentResourceName()),
        defaultMapper = "keyboard",
        defaultKey = "e",
        onPressed = function()
            for _, interaction in pairs(interactions) do
                local success, result = pcall(interaction.condition)
                if success and result then
                    interaction.onPress()
                end
            end
        end
    })

    Remove any restart esx_shops line from server.cfg, restart the server, and rejoin. (Or let this inventory's own shops replace esx_shops, below.)

  • esx_weaponshop ammo and upgrades: it only counts weapons on your ped. At its counters the inventory puts your weapon items on the ped, holstered, so it sees what you own (Config.ESX.StageWeaponsAtShops). Ammo bought there is loaded into that weapon item.

  • Or use this inventory's own shops instead. config/shops.lua, Config.Shops.Mode:

    ModeWhat happens
    'auto' (default)Ours open wherever esx_shops / esx_weaponshop is not running. Remove ensure esx_shops (or esx_weaponshop) and restart: the same counters, items and prices now open in the inventory's shop screen, with blips and an [E] prompt. Ensure it again and ours step aside.
    'lumo'Always ours. Also remove the ESX shops' ensure, or both open at one counter (the console warns).
    'esx'Never ours.

    While esx_shops / esx_weaponshop are installed, their own config (shared/config/shops.lua) supplies the items, prices and positions, so there is one list to edit (UseESXConfig = false uses Config.Shops.Groups instead). Weapon shops also sell ammo, attachment parts (suppressor, clip_extended, scope …, fitted from a weapon's Attachments screen) and tint kits: Config.Shops.WeaponExtras. Licence for legal gun shops: Config.Shops.WeaponLicence = 'weapon' (esx_license).

  • Licences come from esx_license (user_licenses): the firearms licence card shows valid with weapon, the driver's licence with any drive* licence.

  • Weapon wheel: GTA's wheel (TAB) and mouse-wheel weapon switching are blocked, since weapons come from the inventory (Config.Weapons.DisableWeaponWheel).

  • F2: players use TAB. With esx_inventory stopped, F2 does nothing. On older ESX, where the F2 menu is inside es_extended, it still opens ESX's plain list of the same items; unbind it in ESX's keybinds or ignore it.

  • After restarting only lumo-inventory, players already online keep ESX's own functions until they reconnect. Restart the whole server.

Standalone (no framework) ​

For servers without QBCore, Qbox or ESX. Details: Standalone.

  1. Copy lumo-inventory into resources/.
  2. server.cfg:
    cfg
    ensure oxmysql
    ensure ox_lib               # recommended
    ensure lumo-inventory
    ensure lumo-multicharacter  # optional: characters; without it, one inventory per licence
    
    add_principal identifier.license:YOUR_LICENSE group.admin
  3. Restart. Console: [lumo-inventory] ready — framework: standalone, version 1.0.0.

Items come from the built-in list (shared/items.lua, about 330 items), plus anything you add in Config.ExtraItems. Shops are free unless you plug in your money in bridge/config.lua. There are no shop locations built in: create shops from your own script with exports['lumo-inventory']:CreateShop and open them with OpenShop (see INTEGRATION.md). Licences for shops and cards are read from the character's metadata.licences.

Common steps (every framework) ​

Database ​

Nothing to import: on first start the inventory creates inventories (stashes, trunks, gloveboxes) and, on Qbox/ESX/standalone, lumo_inventories (player items). Works on MariaDB and MySQL 8.

If your database user cannot create tables, import qb-inventory.sql by hand. Coming from a very old qb-inventory with stashitems / trunkitems / gloveboxitems tables, run migrate.sql once to move them into inventories.

Targeting ​

With ox_target, qb-target or qtarget, item drops and vending machines get target options (detected automatically). Without one they use an [E] prompt.

Item pictures ​

html/images/<name>.png. The download contains pictures for every built-in item. Add yours with the same file name as the item's image field.

Optional: lumo-ui ​

If lumo-ui runs, it shows the key hints (placing, throwing, carrying) in its strip and the inventory follows its theme. Without it, the hints use your text UI.

Disabling a resource inside a category ​

ensure [qb] starts everything in that folder, so deleting a line does nothing. Make a disabled category and move the old resource there:

resources/
  [qb]/
  [disabled]/              <- create this
    qb-inventory/          <- the old one goes here

Moving from the lumo-bridge edition ​

This edition carries its own copy of the framework layer in bridge/, so it no longer needs the separate lumo-bridge (or lumo-ui) resource.

  1. Replace the whole lumo-inventory folder (do not merge). Copy your config/config.lua changes and your own html/images pictures across.
  2. Move any changes you made in lumo-bridge/config.lua into lumo-inventory/bridge/config.lua.
  3. Replace the shim you use with the new [compat]/qb-inventory or [compat]/ox_inventory so it matches this version. On Qbox, keep your existing data/ files.
  4. Remove ensure lumo-bridge unless other resources still list it.
  5. No database changes.

Test checklist ​

  • [ ] TAB opens the inventory; items survive a relog
  • [ ] Move, split, drop and pick up an item; give one to another player
  • [ ] Open a trunk, a glovebox and a stash; contents stay after a restart
  • [ ] Buy from a shop and a vending machine: money is taken (or free in standalone)
  • [ ] Eat and drink something; use a bandage
  • [ ] Equip a weapon, shoot, holster, relog: ammo is remembered; load an ammo item
  • [ ] Put on a backpack: extra slots appear
  • [ ] /giveitem works for an admin and is refused for a player
  • [ ] ESX: a job/shop script gives an item into this inventory; an existing character still has their old ESX items and weapons
  • [ ] Gun shop: refused without a weapon licence, works with one
  • [ ] Qbox: a 24/7 store and Ammu-Nation open; the police armoury refuses a civilian
  • [ ] ESX: buy at a 24/7 (esx_shops) and a gun plus an upgrade (esx_weaponshop)
  • [ ] ESX: put an item into a job or property storage and take it back out (police armory, property chest); the deposit list shows your current items
  • [ ] Qbox: qbx_core starts; a Qbox script that gives items works