How to Build an Inventory System for a GTA Roleplay Server With AI
The inventory is what makes a GTA roleplay server feel like a world: items have weight, players carry only what fits, a weapon is a physical object you can drop or hand over, and a stash is a real container someone could rob. Today the de facto standard is ox_inventory a slot-based, metadata-aware, server-authoritative inventory that works on ESX, QBCore, and QBox. Building 'an inventory' on a modern server usually means configuring and extending ox_inventory, not reinventing item storage from scratch.
This guide shows how to install ox_inventory cleanly, add and use custom items, register shops and stashes, and add durability or uniqueness with metadata. PlayDeck teaches you to build these extensions with AI: you describe the item, its weight, and what 'using' it should do, then steer the AI as it writes the items.lua entry and the server export and verify it before you sell items packs or systems on Tebex.
Install ox_inventory in the right load order
Load order is the most common reason ox_inventory shows a blank screen or throws bridge errors. Start your resources in dependency order: oxmysql first, then ox_lib, then your framework (es_extended or qb-core), then ox_target, and finally ox_inventory. ox_inventory needs to know your framework, set via a convar (e.g. setr inventory:framework 'qb') so its bridge talks to the right shared object.
Run the included SQL so the inventory tables exist, and on QBCore make sure you disable the old qb-inventory so two inventories aren't fighting. After it loads, an empty inventory that won't open is almost always a load-order or convar problem, not a code bug fix the order before touching anything else. This is exactly the kind of setup an AI can verify against the official docs while you follow along.
Add and use custom items
ox_inventory reads its item catalog from items.lua at startup. Each item has a name (the lowercase key), a label, weight, stack (whether it stacks), and optional flags like close, description, and a client/server use handler. To add an item say a 'lockpick' you add an entry with its weight and a useful description, then restart ox_inventory (or the server) for the change to register. Forgetting the restart is why 'my item doesn't exist' errors appear.
To make an item do something when used, you register a usable item. With ox_inventory you can hook the item's server export or use exports.ox_inventory:Items, or in QBCore register it with the framework's createUseableItem and then remove/add items server-side. The pattern: player uses item, server validates they have it, runs the effect (heal, play an animation, give another item), and removes one from the inventory. When steering an AI, give it the item name, weight, and exact use effect; it writes the catalog entry and the use handler, you confirm the server actually verifies possession before consuming.
Register shops, stashes, and storage
Shops let players buy items. On the server you call exports.ox_inventory:RegisterShop with an id, a list of items and prices, and locations or a target. Note that a server-registered shop can't use client-only features like blips and zones directly you define locations and let the shop framework handle placement. Stashes are persistent shared containers: exports.ox_inventory:RegisterStash with an id, label, slot count, and weight, optionally bound to a job or coordinates, opened via ox_target.
This is how you build trunk storage, gloveboxes, property stashes, and police evidence lockers all the same RegisterStash primitive with different access rules. Because ox_inventory validates every move on the server, two players opening the same stash stay in sync and can't dupe items. Describe the shop catalog or stash (who can open it, how many slots) to your AI and it generates the registration call; you verify the access control, especially for job-restricted stashes.
Use metadata for durability and uniqueness
Metadata is what elevates a slot-based inventory into a roleplay tool. Each item instance can carry a metadata table durability, serial number, owner name, registration, charges left. A repair tool can lose durability per use; a registered weapon can carry a serial that an MDT lookup resolves to a player; a crafted item can store who made it. You set metadata when you add the item server-side and read it wherever the item is used.
Use this for crafting benches (consume inputs with metadata, output an item with quality), for documents (an ID card with the holder's info), and for weapons (ammo, attachments, durability). It is also how you keep items unique so they can't be silently stacked and duped. When you build a crafting or document feature with AI, specify the metadata fields and how they change; the AI wires the read/write, you make sure the server is the one setting metadata, never the client.
Frequently asked questions
Why is my ox_inventory blank or won't open?
Almost always load order or the framework convar. Start oxmysql, ox_lib, your framework, ox_target, then ox_inventory, set inventory:framework correctly, run the SQL, and disable the old inventory. Fix the order before debugging code.
Do I need to restart for new items?
Yes. ox_inventory reads items.lua at startup, so any new or edited item requires restarting the ox_inventory resource (or the whole server) before it exists in game.
How do I make an item usable?
Register it as a usable item with a server handler. When the player uses it, validate they actually hold it on the server, run the effect, then remove one from their inventory. Never trust the client that the item was used.
What is metadata used for?
Per-instance data on a single item: durability, a weapon serial, an ID card holder, charges, or crafted quality. It makes items unique and prevents silent duping, and it powers documents, crafting, and registered weapons.
Can AI add items and shops for me?
Yes. Describe the item's name, weight, and use effect, or the shop catalog and prices, and the AI writes the items.lua entry and the RegisterShop/RegisterStash call. You steer the design and verify server-side validation the exact workflow PlayDeck teaches.