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.
- QBCore
- Qbox (qbx_core)
- ESX (es_extended)
- Standalone (no framework)
- Common steps (every framework)
- Moving from the lumo-bridge edition
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 QboxMove 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.
| Stop | Keep | Shops come from | |
|---|---|---|---|
| QBCore | qb-inventory (replaced by the [compat]/qb-inventory shim) | qb-shops, qb-weapons (optional), qb-target | qb-shops: its licence, job and grade rules are checked here on every purchase |
| Qbox | the real ox_inventory (replaced by the [compat]/ox_inventory shim) | ox_lib, ox_target, every qbx script | The shim's data/shops.lua: ~45 shops ship with it. No other shop script needed |
| ESX | esx_inventory (F2 menu), esx_inventoryhud, any other inventory | esx_shops, esx_weaponshop, esx_license, esx_addoninventory | esx_shops (set Config.Inventory = 'esx') and esx_weaponshop (needs esx_license) |
| Standalone | any 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.
- Copy
lumo-inventoryintoresources/(any category, e.g.[lumo]). - Remove the real qb-inventory: move its folder out of
[qb]into a category nothing starts (see Disabling a resource). - Move
[compat]/qb-inventorytoresources/[qb]/qb-inventory(where the old one was), and delete the rest of[compat]. server.cfg:cfgThe shim depends on lumo-inventory, so FiveM starts lumo-inventory first even ifensure oxmysql ensure qb-core ensure lumo-inventory ensure [qb] # includes the qb-inventory shim, qb-weapons, qb-target …[qb]comes earlier.- 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'sinventoriestable. 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'simageinqb-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), setConfig.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.
- Copy
lumo-inventoryintoresources/. - 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). - Move
[compat]/ox_inventorytoresources/ox_inventory, and delete the rest of[compat]. - Your items and shops. The shim ships
data/items.luaanddata/weapons.luamade from the built-in item list, anddata/shops.luawith 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 aswater,burger), copy your oldox_inventory/data/items.lua,weapons.luaandshops.luaover them, and your old item pictures (ox_inventory/web/images/*.png) intolumo-inventory/html/images/. Keep theWeapons,AmmoandComponentskeys inweapons.luaeven if empty; qbx_core reads all three. Every weapon inweapons.luabecomes a usable weapon item on its own (lower case, e.g.weapon_pistol); you do not have to list weapons initems.lua. server.cfg, the inventory before[ox]and[qbx]:cfgKeepensure ox_lib ensure oxmysql ensure qbx_core ensure ox_target ensure lumo-inventory ensure ox_inventory # the shim ensure [ox] ensure [qbx]setr inventory:framework "qbx"in your config; qbx_core reads it.- Restart. Console:
[lumo-inventory] player items are stored in `lumo_inventories`.`items` [lumo-inventory] ready — framework: qbx, version 1.0.0qbx_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:
- Weapons: drawn by the built-in weapon handler (no qb-weapons on Qbox).
- Food and drink:
Config.Consumablesinconfig/config.lua, or, for anything not listed there, the item's own oxclient.statusinitems.lua(status = { hunger = 200000 }fills 20 % of the bar, as on ox_inventory). - Everything else: a handler a script registered with
exports.qbx_core:CreateUseableItem(name, fn)(orexports['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'splayers.inventorycolumn belongs to ox_inventory's format and is never touched, so moving back is just swapping the folders again. - ox hooks (
registerHook):openInventoryfires, 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.luaformat, and the rules in it are enforced:groups(only those jobs/gangs can open the shop),licenseon an item (needs that licence in the character'smetadata.licences, e.g. the weapon licence for guns) andgrade(minimum job grade). Scripts that add shops withexports.ox_inventory:RegisterShopwork 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-9etc.: add them toConfig.Weapons.Ammoif 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).
Copy
lumo-inventoryintoresources/.Stop the ESX inventory screens, keep the storage:
Resource What it is Do esx_inventory(in[core]on recent ESX Legacy, e.g. 1.15)ESX's old F2 item menu Stop it: move it out of [core](e.g. into adisabledfolder) or remove itsensureesx_inventoryhud, ox_inventory, any other inventoryA second inventory Stop 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 core Keep. Its inventory functions are taken over automatically Do not install the
ox_inventoryshim on ESX: ESX would switch to its ox mode. LeaveConfig.CustomInventory = falsein es_extended's config.server.cfg:cfgensure oxmysql ensure ox_lib # recommended: progress bars and prompts ensure es_extended ensure lumo-inventory ensure [esx_addons] # your ESX scripts, after the inventoryRestart 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 withConfig.ESX.ImportESXInventory = false.Items come from ESX's
itemstable (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 = 1000converts (bread1= 1000 g). Give ESX-only items a picture by savinghtml/images/<itemname>.png.Weapons are items.
xPlayer.addWeapon('WEAPON_PISTOL', 50)gives aweapon_pistolitem 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.RegisterUsableItemwork from the inventory. Food and drink listed inConfig.Consumablesare handled by the inventory itself and feedesx_status(hunger/thirst).Money stays in ESX accounts:
cashmaps tomoney,banktobank.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) orESX.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.luaand setConfig.Inventory = 'esx', so purchases go throughxPlayer.addInventoryIteminto 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'sitemstable (shop label,Config.ESX.ShopItemWeightgrams), and shows esx_shops' picture (nui://esx_shops/web/images/…). Other shop resources with the same config layout: add them toConfig.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 = falseinesx_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 usesxLib.interactionsregisters the same+esx_interactkey command, and a command belongs to one resource only. Fix it once in[core]/esx_lib/imports/interactions/client.lua: replace everything fromfunction xLib.interactions.getInteractKey()down to thexLib.addKeybind({ … })block's closing})withlua-- 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_shopsline 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:Mode What happens 'auto'(default)Ours open wherever esx_shops / esx_weaponshop is not running. Remove ensure esx_shops(oresx_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 = falseusesConfig.Shops.Groupsinstead). 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 withweapon, the driver's licence with anydrive*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_inventorystopped, 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.
- Copy
lumo-inventoryintoresources/. server.cfg:cfgensure 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- 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 hereMoving 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.
- Replace the whole
lumo-inventoryfolder (do not merge). Copy yourconfig/config.luachanges and your ownhtml/imagespictures across. - Move any changes you made in
lumo-bridge/config.luaintolumo-inventory/bridge/config.lua. - Replace the shim you use with the new
[compat]/qb-inventoryor[compat]/ox_inventoryso it matches this version. On Qbox, keep your existingdata/files. - Remove
ensure lumo-bridgeunless other resources still list it. - 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
- [ ]
/giveitemworks 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