Items
inventory: give, take and count items, stashes, shops and usable items through whatever inventory the server runs.
import { inventory } from "@aicore-fivem/lib/server";inventory sends every item call through ai-core's inventory layer: the inventory the server runs (ai-inventory, or another the owner picks in ai-core's panel) answers. Your script never calls an inventory's own exports, so it keeps working when the owner changes inventory.
The inventory argument (inv, type InventoryRef) is a player's server id (a number) or another inventory's id (a string: a stash name, a plate).
Counts are whole numbers of 1 or more; a fraction is rounded down, 0 or a negative count makes the call fail.
While no inventory runs, calls fail quietly: false, 0, an empty list or null. The Lua twins on aiLib.inventory have the same names and argument order.
inventory.addItem
Gives items to an inventory.
Side: Server · Waits: no
inventory.addItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): booleanlocal ok = aiLib.inventory.addItem(inv, item, count, metadata, slot)Parameters
Prop
Type
Returns
boolean: true when given. false when they do not fit, the item does not exist, an argument is wrong or no inventory runs.
Example
import { inventory } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
if (!inventory.addItem(source, "phone", 1, { number: "555-0101" })) return fail("INVENTORY_FULL");Check canCarryItem first when you take something in exchange (money, another item): take it only after addItem answered true, or give it back.
inventory.removeItem
Takes items from an inventory.
Side: Server · Waits: no
inventory.removeItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): booleanlocal ok = aiLib.inventory.removeItem(inv, item, count, metadata, slot)Parameters
Prop
Type
Returns
boolean: true when taken. false when there are not enough, an argument is wrong or no inventory runs.
Example
if (!inventory.removeItem(source, "lockpick")) return fail("NO_LOCKPICK");inventory.getItemCount
How many of an item an inventory holds.
Side: Server · Waits: no
inventory.getItemCount(inv: InventoryRef, item: string, metadata?: ItemMetadata): numberlocal count = aiLib.inventory.getItemCount(inv, item, metadata)Prop
Type
Returns
number: the total over every stack, 0 when none or no inventory runs.
Example
const bags = inventory.getItemCount(source, "weed_bag");
notify(source, `You have ${bags} bags`);inventory.hasItem
Whether an inventory holds at least count of an item.
Side: Server · Waits: no
inventory.hasItem(inv: InventoryRef, item: string, count?: number): booleanlocal has = aiLib.inventory.hasItem(inv, item, count)Prop
Type
Returns
boolean.
Example
if (!inventory.hasItem(source, "scrap_metal", 10)) return fail("NEED_10_SCRAP");hasItem is a check, not a hold: between hasItem and removeItem (an await in between) the item can leave. Act on the answer of removeItem.
inventory.canCarryItem
Whether the items would fit (weight and free space).
Side: Server · Waits: no
inventory.canCarryItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata): booleanlocal fits = aiLib.inventory.canCarryItem(inv, item, count, metadata)Prop
Type
Returns
boolean: true when they fit.
Example
if (!inventory.canCarryItem(source, "fish", 5)) return fail("TOO_HEAVY");
inventory.addItem(source, "fish", 5);inventory.getItems
Every stack of an inventory.
Side: Server · Waits: no
inventory.getItems(inv: InventoryRef): InventoryStack[]local stacks = aiLib.inventory.getItems(inv)Returns
InventoryStack[]: one { name, label, count, slot, metadata } per stack. Empty when the inventory is empty, unknown or no inventory runs.
Example
const weapons = inventory.getItems(source).filter((stack) => stack.name.startsWith("weapon_"));inventory.clearInventory
Empties an inventory.
Side: Server · Waits: no
inventory.clearInventory(inv: InventoryRef): voidaiLib.inventory.clearInventory(inv)Returns
void.
Example
inventory.clearInventory("evidence_locker_12");inventory.registerStash
Registers a stash (a storage box, a locker). ai-core remembers it and registers it again with any inventory that starts later, so call it once when your script starts.
Side: Server · Waits: no
inventory.registerStash(name: string, label: string, slots: number, maxWeight: number, jobs?: string[]): voidaiLib.inventory.registerStash(name, label, slots, maxWeight, jobs)Parameters
Prop
Type
Returns
void.
Example
inventory.registerStash("police_armory", "Armory", 50, 200_000, ["police"]);inventory.openInventory
Opens a stash or another player's inventory on a player's screen.
Side: Server · Waits: no
inventory.openInventory(source: number, inv: InventoryRef): booleanlocal ok = aiLib.inventory.openInventory(source, inv)Prop
Type
Returns
boolean: true when the inventory opened it.
Example
import { onClientCallback, near, online, inventory } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
const ARMORY = { x: 452.3, y: -980.0, z: 30.7 };
onClientCallback(
"my-police:armory",
(source) => {
if (!online.onDutyIn(source, ["police"])) return fail("NOT_ON_DUTY");
return { ok: inventory.openInventory(source, "police_armory") };
},
{ guards: [near(ARMORY, 3)] },
);No range or access check happens here: check distance, job and ownership before you call it.
inventory.registerUsableItem
Runs your handler when a player uses an item. ai-core keeps the handler for inventories that start later and across inventory restarts, so register once when your script starts.
Side: Server · Waits: no
inventory.registerUsableItem(name: string, handler: UsableItemHandler): voidaiLib.inventory.registerUsableItem(name, handler) -- handler(source, item)Parameters
Prop
Type
The used stack is a UsedItem.
Inventories that take a used item themselves (ai-inventory) take it as soon as the handler returns anything but false. When your handler waits (a progress bar) and removes the item itself, return false at once, or the item is taken twice.
Returns
void.
Example
import { inventory, progressFor, medical, createLocale } from "@aicore-fivem/lib/server";
const Locale = createLocale();
async function bandage(source: number) {
const done = await progressFor(source, { label: Locale("BANDAGING"), duration: 4000, canCancel: true });
if (done && inventory.removeItem(source, "bandage")) medical.heal(source);
}
inventory.registerUsableItem("bandage", (source) => {
void bandage(source);
return false; // keep the item now: bandage() takes it after the bar
});inventory.getItemDefinition
An item's label, weight and flags.
Side: Server · Waits: no
inventory.getItemDefinition(name: string): ItemDefinition | nulllocal def = aiLib.inventory.getItemDefinition(name)Returns
ItemDefinition (name, label, weight, unique, close, description, image?), or null when the inventory does not know the item.
Example
const label = inventory.getItemDefinition("water")?.label ?? "water";
notify(source, `You bought ${label}`, "success");inventory.registerShop
Registers a shop the server opens for a player (it has no place of its own). ai-core registers it again with any inventory that starts later; call it once at start.
Side: Server · Waits: no
inventory.registerShop(name: string, label: string, items: ShopProduct[]): voidaiLib.inventory.registerShop(name, label, items)Prop
Type
Returns
void.
Example
inventory.registerShop("police_shop", "Police supplies", [
{ name: "handcuffs", price: 0 },
{ name: "radio", price: 50 },
]);inventory.openShop
Opens a registered shop on a player's screen.
Side: Server · Waits: no
inventory.openShop(source: number, name: string): booleanlocal ok = aiLib.inventory.openShop(source, name)Returns
boolean: true when it opened.
Example
onClientCallback("my-police:shop", (source) => {
if (!online.onDutyIn(source, ["police"])) return fail("NOT_ON_DUTY");
return { ok: inventory.openShop(source, "police_shop") };
});No range or access check happens here: check them before you call it.