ATY Scripts Logo
ATY Scripts/Docs/Inventory/Compatibility

Compatibility

Compatibility

Other resources call qb-inventory and ox_inventory by name — that is how FiveM exports work, an export is addressed to a resource name and nothing else. This resource answers to both names, so scripts written for either one keep working without being edited.

**tl;dr — install the proxy, change nothing else.** Stop the real `qb-inventory` / `ox_inventory`, `ensure` the matching folder from `compat/` under that same name, and every third-party script that called the old inventory now reaches this one. See Quick install below.

Why this is needed at all

exports.ox_inventory:AddItem(...) only works if a resource literally named ox_inventory is running and has registered an AddItem export. There is no alias mechanism in FiveM — the name in the export call IS the address. So if a server switches its inventory to aty_inventory but a weapon shop script still says exports.ox_inventory:AddItem(...), that call goes nowhere unless something answers to the name ox_inventory.

compat/qb-inventory/ and compat/ox_inventory/ are that something. Each is a tiny resource folder — a few dozen lines, no state, no database access — whose only job is to sit under the old name and forward every call straight to aty_inventory. Read server/api/ox.lua or compat/ox_inventory/server.lua if you want to see exactly what "forward" means; there is nothing hidden in it.

Quick install

ensure aty_lib
ensure aty_inventory

# pick whichever names your other scripts actually call —
# install both if you are not sure, it is harmless to run both
ensure qb-inventory      # the proxy from compat/qb-inventory, NOT the original
ensure ox_inventory      # the proxy from compat/ox_inventory, NOT the original
  1. Stop or delete the real qb-inventory / ox_inventory folder first. Two resources cannot share one name — if the genuine one is still present and started, the proxy will either fail to start or (worse) start and race it, and which one answers a given call becomes load order, not a setting.
  2. Copy compat/qb-inventory/ and/or compat/ox_inventory/ out to your resources/ folder — they can live anywhere, they only need to keep their folder name.
  3. ensure them after aty_inventory in server.cfg. Order relative to each other does not matter.
  4. Run invdoctor in the server console. A correct install prints a line like "ox_inventory is this resource wearing that name" — see Troubleshooting below for what a wrong install looks like.
**Qbox needs one more thing, and it is an ordering rule.**

Qbox ships ox_inventory, so step 1 is not optional there — leaving it installed means aty_inventory starts, shows up in the loading screen, and F2 still opens the old inventory, because that is the resource still answering to the name.

On top of that, qbx_core reads the item list out of ox_inventory's own files while it is starting (require '@ox_inventory.data.items'). The proxy serves those files from the live catalogue, which means it has to be able to reach aty_inventory by then:

ensure aty_lib
ensure aty_inventory     # before the core, not after
ensure ox_inventory      # the proxy from compat/
ensure qbx_core

Get that order wrong and the core starts believing the server has no items. The proxy hands back an empty list rather than an error — an error there would take the core, and everything that depends on it, down with it — and says so in the console: data/items.lua was read before aty_inventory could answer, followed by the line that names the fix.

What Qbox answers for

aty_lib matches a framework by resource name and knows qb-core and es_extended; Qbox is neither, so the bridge reports no framework. This resource asks qbx_core itself for the four things that matter:

Question On Qbox
Identity PlayerData.citizenid — the character, not the account
Job and gang PlayerData.job / .gang, so job gates gate
Needs hunger and thirst metadata, plus the HUD event
Money qbx_core's GetMoney / AddMoney / RemoveMoney exports
invwallet <playerId>     which backend holds the money, and what it reads

Before 1.7.4 none of that happened: the resource ran its standalone answers, so money meant the cash item and never the wallet, and every character on one account shared a bag.

**Upgrading a Qbox server from 1.7.3 or earlier.** Bags were keyed on the licence and are now keyed on the citizenid. Back up `aty_inventories`, then run `invqbxkeys` to see what would move and `invqbxkeys confirm` to move it.

Cash as an item on Qbox

qbx_core keeps every account named in the convar inventory:accounts (default ["money"]) as an item of its own, and writes it through exports.ox_inventory:SetItem — which on this setup is the proxy, so the money item lands in this inventory. That item weighs nothing and has no stack limit, unlike Config.Money.stack for mirrored cash: Qbox writes the whole balance in one set and never retries, so it must always fit in one slot.

The mirror keeps that money item and the wallet equal in both directions, as ox_inventory's own Qbox bridge does: Qbox's writes bring the item up to the wallet, and dropping, handing over or RemoveItem-ing the item moves the wallet. cash copies an older mirror left in bags are taken back once. With no money definition to adopt (no parked ox_inventory), cash stands in for it.

aty_escmenu

When aty_escmenu replaces the pause menu, the game reports no pause menu open. The inventory also reads the escMenuOpen state bag, so it does not open underneath it, and container blips are named for its map panel.

The proxies are deliberately **not** declared as dependencies of `aty_inventory`. FiveM stops every dependant when a dependency restarts and does not bring them back — if the proxy depended on `aty_inventory`, a plain `restart aty_inventory` would silently kill the proxy, and every third-party script would go dark until someone noticed and restarted it by hand. A server that does not need a proxy also should not be forced to run one.

"Do I need to change Config.Inventory in my other scripts?"

No — leave it exactly as it is. This is the single most common question about this compatibility layer, so it gets its own answer:

A lot of multi-framework scripts have something like:

Config.Inventory = 'ox_inventory'
-- …
exports[Config.Inventory]:AddItem(src, 'water', 1)

That code does not care what inventory is actually running — it only cares that a resource named ox_inventory answers AddItem the way ox does. Once the proxy is installed under that name, it does exactly that. Changing Config.Inventory to 'aty_inventory' does not make this MORE compatible — it breaks it, because the script almost certainly has no branch for 'aty_inventory' at all and falls through to nothing. Leave the value alone; the proxy's whole purpose is to make that value keep being true.

Two ways to use it

A — install the proxy (recommended). Covered above. Nothing to touch in any other resource, ever, as long as the export it calls is on the list below.

B — call this resource directly, for new code or code you are already editing anyway, without installing a second resource folder at all:

-- qb-style, prefixed directly on aty_inventory
exports.aty_inventory:qb_AddItem(src, 'water', 1)
exports.aty_inventory:qb_RemoveItem(src, 'water', 1)
exports.aty_inventory:qb_GetInventory(src)
exports.aty_inventory:qb_GetItemCount(src, 'water')
exports.aty_inventory:qb_ClearInventory(src)
-- client: exports.aty_inventory:qb_GetPlayerItems()

-- ox-style, native names on aty_inventory (only the two that
-- collide with this resource's own shape need the ox_ prefix)
exports.aty_inventory:AddItem(inv, 'water', 1)
exports.aty_inventory:ox_GetInventory(inv)
exports.aty_inventory:ox_GetInventoryWeight(inv)

The ox_inventory export surface, in full

This is not a small convenience shim — it is the entire ox server and client API, reimplemented with ox's own argument order and return shapes (server/api/ox.lua). Ox's Search has a genuinely odd asymmetry — a single item name returns a bare value, a list of names returns a keyed table — and that asymmetry is reproduced on purpose, not "cleaned up", because real scripts written against ox depend on it.

Every one of these still goes through the same transaction engine a player uses when dragging an item by hand: weight limits, stacking rules, the optimistic lock and the ledger all apply. This is a second name, never a second, unchecked path into the data.

CategoryExports
Add / removeAddItem · RemoveItem
ReadingSearch · GetItem · GetItemCount · GetInventoryItems
Slot lookupsGetSlot · GetSlotIdWithItem · GetSlotWithItem · GetSlotsWithItem · GetSlotIdsWithItem
Capacity checksCanCarryItem · CanCarryWeight · CanCarryAmount · GetInventoryMaxWeight
Writing stateSetMetadata · SetDurability · ClearInventory · SetMaxWeight · SetSlotCount
Slot planningGetEmptySlot · GetItemSlots · GetSlotForItem · CanSwapItem
Moving & settingSetItem · SwapSlots
ContainersRegisterStash · CreateTemporaryStash · GetContainerFromSlot · forceOpenInventory · InspectInventory · RemoveInventory
ShopsRegisterShop
Police pairConfiscateInventory · ReturnInventory
Vehicles & weaponsUpdateVehicle · GetCurrentWeapon
Ground dropsCreateDropFromPlayer · CustomDrop
CatalogueItems · ItemList
HooksregisterHook · removeHooks
Framework glue
(called by ESX's own ox bridge)
setPlayerInventory
pefcl bankinggetCash · getBank · addCash · removeCash · getCards · giveCard
getCards / giveCard answer empty and say why: bank cards are not modelled here
Present, but says so
(registered so the call cannot throw; prints one line explaining what it does instead)
ConvertItems
bulk conversion runs through invimport, which shows a dry run first
Prefixed
(name collides with this resource's own shape)
ox_GetInventory · ox_GetInventoryWeight
reachable under ox's own names as GetInventory and Inventory

Client side:

CategoryExports
What you carryGetPlayerItems · GetItemCount
WeightGetPlayerWeight · GetPlayerMaxWeight
ReadingSearch · Items · ItemList
Slot lookupsGetSlotWithItem · GetSlotsWithItem · GetSlotIdWithItem · GetSlotIdsWithItem
ActinguseItem · useSlot · giveItemToTarget
WeaponsgetCurrentWeapon · weaponWheel
The panelopenInventory · closeInventory · openNearbyInventory
Noticesnotify
Progress barProgress · ProgressActive · CancelProgress
Present, but says so
(registered so the call cannot throw; each prints one line explaining what it does instead)
Keyboard · setStashTarget · displayMetadata
**The progress bar and the last row are worth understanding before you rely on them.**

Progress draws this resource's own bar and runs it for the full duration: label, canCancel, useWhileDead and disable are honoured, and as in ox the callback is told whether it was cancelled while the export returns whether it finished. anim and prop are not played — they would fight the animations this resource plays for its own actions — and the console says so once. A bar that reported "finished" without ever running would make a script hand out its reward instantly, so this one always runs.

Keyboard is ox re-publishing ox_lib's input dialog under its own name. It is not an inventory feature and there is no general dialog here to hand back, so it returns nil; call lib.inputDialog directly. weaponWheel can only hold the wheel off — Config.Weapons.wheel = false still wins over any script.

A few of these behave on screen as ox's do. A hook that returns false prints [hooks] hook_N (<resource>) rejected <event> in the server console (ox's inventory:loghookrejection, on by default), and options.print = true logs every run of that hook. ConfiscateInventory closes the player's open inventory; ReturnInventory closes it and tells the player their items were given back. As in ox, a ReturnInventory for a player with nothing held does nothing at all, so a jail script may call it on every release.

**Not on either list?** Both lists are checked against ox's own source by `invoxapi` (the exports this resource publishes) and `invoxproxy` (the same names reached as `exports.ox_inventory:X()`, which is the path your script actually takes). If a name is genuinely absent, the proxy has nothing registered under it, so the call resolves to `nil` and errors the way any missing export does — this is not a silent failure, the calling script's own error handling (or lack of it) is what decides what happens next. Two ways to close the gap: add the name to the `MAP` table at the top of `compat/ox_inventory/server.lua` (or `client.lua`) — it forwards to the export of that name on `aty_inventory`, so the export has to exist there too — or rewrite that one call against this resource's own native exports in Exports — most ox exports not on this list have a same-named or clearly equivalent native export already.

Troubleshooting

Run invdoctor first, always — it is read-only and checks exactly the things that go wrong with a compatibility install:

  • `ox_inventory` is this resource wearing that name — correct install, nothing to do.
  • `ox_inventory` is running as well as this one — the real ox_inventory is still present and started alongside the proxy or aty_inventory itself. Stop it in server.cfg; which one of two live inventories answers a given call is load order, not a setting, and this is by a wide margin the most common "it's broken" report that turns out not to be a bug at all.

If the resource names all check out but a specific call still misbehaves, two more read-only commands narrow it down further:

  • invbridge — asks aty_lib live what inventory it thinks is running, rather than trusting a snapshot taken at boot. If a bridge-based aty_* resource (a shop script, a crafting bench) is writing metadata that never shows up, this is usually why: the bridge resolved a different or no inventory in the up-to-ten-second window after startup, and every write since has gone through that stale answer.
  • invforeign — checks that items and use-handlers registered by other resources (the qb-core catalogue, a CreateUseableItem call from an old script) were actually adopted and still work, and that this resource's own registration wins when both sides claim the same item name. Useful when "drop it in, change nothing" doesn't seem to hold for one specific item.

Self-identification

A proxy answers a hidden export, AtyProxyTarget, when asked — it returns the name of the resource it forwards to. This is exactly how invdoctor tells "a rival inventory is genuinely running" apart from "this is our own installer wearing that name": both look identical from GetResourceState alone, and a doctor that flags its own installer as a conflict is one people learn to ignore, which buries the finding that actually matters.

The framework mirror

Config.QbMirror = { … }

Some framework code (qb-core's own scripts, mostly) reads a player's inventory straight out of QBCore.Functions.GetPlayerData().items instead of asking any inventory resource by export. No proxy fixes that — there is no export call to intercept. The mirror writes that table back on every inventory change instead, so those reads stay correct without the reading code being touched at all.

invmirror       inspect what the mirror currently holds for a player
invbridge       inspect what aty_lib resolved the inventory to be
invforeign      check that foreign items/handlers were adopted correctly

See Migration for moving the data — existing player inventories and stash contents — across from qb-inventory or ox_inventory. This page is only about keeping other resources' code working; that page is about not losing anyone's items along the way.

ATY Scripts LogoATY SCRIPTS

Des scripts FiveM hautement optimisés pour QBCore & ESX. Performance maximale, code précis, zéro lag.

Rejoindre la communauté

Partenaire

Partenaire officiel de Tebex. Paiement sécurisé et intégration Cfx.re Keymaster.

Mentions légales

Non affilié à Rockstar Games, Cfx.re, FiveM ou Take-Two Interactive. Les achats sont soumis aux CGU de Tebex.

© 2026 ATY SCRIPTS. Tous droits réservés.