One Studios
Server

Exports

Server-side exports.

All server exports are called as exports.one_inventory:Name(...) from a server script.

Inventory identifiers

Every server export below takes an inv argument that resolves to a single inventory. The same export works for players, stashes, vehicle trunks, gloveboxes, containers, drops, and dumpsters, so a dealership script can pre-fill a trunk the same way a player script tops up a container.

FormResolves to
123Player by server id/source
'123'Player by server id/source
'player:<identifier>'Player by getIdentifier()
'stash:<name>'Shared stash
'stash:<name>:<identifier>'Owned / unique stash bucket
'trunk:<plate>'Vehicle trunk
'glovebox:<plate>'Vehicle glovebox
'container:<id>'Container instance
'drop:<id>'Ground drop
'dumpster:<id>'Dumpster

Auto-create on first call

AddItem and SetItem materialise the inventory on first call when the type supports it. Every other export returns false / nil for an inventory that doesn't exist yet.

TypeAuto-creates?Defaults
stash:*yes50 slots / 50 000 g
trunk:*yes30 slots / 80 000 g
glovebox:*yes5 slots / 5 000 g
drop:*, container:*, dumpster:*, player:*no—

Slot table format

Every export below that returns a slot returns the same standardized table.

name
string
Item definition name.
slot
number
Slot index the item sits in.
count
number
Stack count in the slot.
weight
number
The slot's effective weight in grams (per-unit weight times count).
metadata
table
The full metadata table. Per-item data lives here: ammo, serial, components, and any custom keys. Absent when the slot has none.
label
string
Display label, from the item definition.
description
string
Description, from the item definition.
image
string
Image name, from the item definition.

Item operations

AddItem

Add a count of an item to an inventory.

exports.one_inventory:AddItem(inv, item, count, metadata, slot)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
Item name.
count
number
Defaults to 1.
metadata
table
Metadata override merged with definition defaults.
slot
number
Force the item into a specific slot.
Auto-creates stash:*, trunk:*, and glovebox:* inventories if they don't exist yet. See Auto-create on first call.
Serial-less weapons: pass metadata.serial = false to add a weapon without a serial number (e.g. blackmarket guns):
exports.one_inventory:AddItem(inv, 'weapon_pistol', 1, { serial = false })

Returns: boolean, string? - success, plus a reason on failure (invalid_item, no_inventory, hook_cancelled, ...).


RemoveItem

Remove a count of an item from an inventory. Auto-disarms if a player's equipped weapon is removed.

exports.one_inventory:RemoveItem(inv, item, count, metadata, slot)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
count
number
Defaults to 1.
metadata
table
Metadata filter (only removes slots whose metadata matches).
slot
number
Restrict removal to this slot only.

Returns: boolean, string?.


SetItem

Set the absolute count of an item across an inventory (creates / destroys stacks to match).

exports.one_inventory:SetItem(inv, item, count, metadata)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
count
number required
Target total count (0 to remove all).
metadata
table
Metadata filter for matching slots.
Auto-creates stash:*, trunk:*, and glovebox:* inventories if they don't exist yet. See Auto-create on first call.

Returns: boolean, string?.


GetItem

First slot matching the given item name (and optional metadata).

exports.one_inventory:GetItem(inv, item, metadata)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
metadata
table

Returns: table | nil - a slot table, or nil if not found.


GetItemCount

Total count of an item across every slot of the inventory.

exports.one_inventory:GetItemCount(inv, item, metadata)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
Item name.
metadata
table
Optional metadata filter.

Returns: number.


HasItem

True when the inventory holds at least count of the item.

exports.one_inventory:HasItem(inv, item, count, metadata)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
Item name.
count
number
Defaults to 1.
metadata
table
Optional metadata filter.

Returns: boolean.

Slot lookup

GetSlot

Slot data at a given slot index.

exports.one_inventory:GetSlot(inv, slot)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
slot
number required
Slot index to read.

Returns: table | nil - a slot table, or nil if empty / out of range.


GetFreeSlot

First empty slot in the inventory.

exports.one_inventory:GetFreeSlot(inv)
inv
string | number required
Inventory to operate on. See Inventory identifiers.

Returns: number | nil.


GetSlotIdWithItem

First slot index that contains the item, optionally filtered by metadata.

exports.one_inventory:GetSlotIdWithItem(inv, item, metadata)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
Item name to match.
metadata
table
Optional metadata filter.

Returns: number | nil.


GetSlotIdsWithItem

Every slot index that contains the item.

exports.one_inventory:GetSlotIdsWithItem(inv, item, metadata)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
Item name to match.
metadata
table
Optional metadata filter.

Returns: number[].


GetItemSlots

Map of { [slotId] = count } for every slot containing the item.

exports.one_inventory:GetItemSlots(inv, item)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
Item name to match.

Returns: table<number, number>.


GetContainerFromSlot

Container item at a slot.

exports.one_inventory:GetContainerFromSlot(inv, slot)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
slot
number required
Slot index to read.

Returns: table | nil - a slot table plus slots and maxWeight, with the contents snapshot under metadata.items. nil if the slot doesn't hold a container.


GetEquippedWeapon

Currently-equipped weapon slot.

exports.one_inventory:GetEquippedWeapon(inv)
inv
string | number required
Player to read. Non-player inventories return nil.

Returns: table | nil - a slot table where metadata holds ammo / serial / components, or nil if unarmed.

Capacity

CanCarryItem

True if the inventory can still fit N more of the item.

exports.one_inventory:CanCarryItem(inv, item, count)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
Item name.
count
number
Defaults to 1.

Returns: boolean.


CanCarryWeight

True if the inventory can take an additional weight grams.

exports.one_inventory:CanCarryWeight(inv, weight)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
weight
number required
Additional grams to check for.

Returns: boolean.


GetCarryableCount

Max additional units of the item that still fit (math.huge for zero-weight items).

exports.one_inventory:GetCarryableCount(inv, item)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
item
string required
Item name.

Returns: number.


SwapSlots

Swap the contents of two slots within the same inventory.

exports.one_inventory:SwapSlots(inv, fromSlot, toSlot)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
fromSlot
number required
Slot to move from.
toSlot
number required
Slot to move into.

Returns: boolean.


CanSwapItems

True if a fromItem ↔ toItem swap (inventory gives fromItem, receives toItem) would still fit under its max weight.

exports.one_inventory:CanSwapItems(inv, fromItem, fromCount, toItem, toCount)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
fromItem
string required
Item the inventory gives up.
fromCount
number required
Count of fromItem given up.
toItem
string required
Item the inventory receives.
toCount
number required
Count of toItem received.

Returns: boolean.

Item-level writes

SetItemDurability

Overwrite the durability percent on a single slot (0-100). Updates the degrade timestamp.

exports.one_inventory:SetItemDurability(inv, slot, value)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
slot
number required
Slot to update.
value
number required
Durability between 0 and 100.

Returns: boolean.


SetItemMetadata

Replace the metadata table on a single slot (full overwrite, not a merge).

exports.one_inventory:SetItemMetadata(inv, slot, metadata)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
slot
number required
Slot to update.
metadata
table required
Replacement metadata table.

Returns: boolean.

Inventory-level writes

SetInventoryMaxWeight

Live-update the inventory's max weight (grams).

exports.one_inventory:SetInventoryMaxWeight(inv, weight)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
weight
number required
New max weight in grams.

Returns: boolean.


SetInventorySlotCount

Live-update the inventory's slot count. Items in slots beyond the new range are discarded.

exports.one_inventory:SetInventorySlotCount(inv, count)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
count
number required
New slot count.

Returns: boolean.


ClearInventory

Empty an inventory.

exports.one_inventory:ClearInventory(inv, keep, clearClothing)
inv
string | number required
Inventory to operate on. See Inventory identifiers.
keep
string[]
Optional array of item names to preserve.
clearClothing
boolean
Player only. When true, also wipes equipped clothing and strips the ped. Silently ignored for non-player inventories.

Returns: boolean, string?.

Wholesale reads

GetInventory

Full snapshot of the inventory.

exports.one_inventory:GetInventory(inv)
inv
string | number required
Inventory to read. See Inventory identifiers.

Returns: table | nil - { type, id, label, weight, maxWeight, maxSlots, slots, ... }, where each entry in slots is a slot table.


GetInventoryItems

Flat array of every occupied slot in the inventory.

exports.one_inventory:GetInventoryItems(inv)
inv
string | number required
Inventory to read. See Inventory identifiers.

Returns: table[] - an array of slot tables.


SearchInventory

Every slot matching query (optionally filtered by metadata).

exports.one_inventory:SearchInventory(inv, query, metadata)
inv
string | number required
Inventory to search. See Inventory identifiers.
query
string required
Item name to match. Compared exactly (==) against each slot's name.
metadata
table
Optional metadata filter. A slot matches only when, for every key in this table, the slot's metadata holds the same value (shallow equality). Omit to match the item regardless of metadata.

Returns: table[] - array of matching slot tables; empty when nothing matches.


GetWeightHolding

Current weight in grams stored in the inventory.

exports.one_inventory:GetWeightHolding(inv)
inv
string | number required
Inventory to read. See Inventory identifiers.

Returns: number.


GetWeightLeft

Remaining weight capacity in grams (maxWeight - weight).

exports.one_inventory:GetWeightLeft(inv)
inv
string | number required
Inventory to read. See Inventory identifiers.

Returns: number.

Definitions

GetItemDefinition

Definition by name. Resolves any definition type (item, weapon, ammo, component, container, clothing), not just items. The returned table carries a type field tagging which kind it is.

exports.one_inventory:GetItemDefinition(name)
name
string required
Definition name.

Returns: table | nil - the definition with an added type field, or nil if unknown.


GetAllItemDefinitions

Every definition keyed by name. Returns all definition types (item, weapon, ammo, component, container, clothing), each tagged with a type field.

exports.one_inventory:GetAllItemDefinitions(filter)
filter
string | string[]
Narrow to one or more types, e.g. 'weapon' or { 'weapon', 'ammo' }. Omit (or pass an empty value) to return everything.

Returns: table<string, table> - map of { [name] = definition }; each definition carries a type field.

-- every definition
local all = exports.one_inventory:GetAllItemDefinitions()

-- only weapons and ammo
local guns = exports.one_inventory:GetAllItemDefinitions({ 'weapon', 'ammo' })

These definition lists rarely change at runtime, so most scripts call them once and cache the result. When a definition is created, edited, or deleted from any source, the one_inventory:onDefinitionsUpdated event fires (coalesced, no payload). Rebuild your cache from it:

AddEventHandler('one_inventory:onDefinitionsUpdated', function()
    local defs = exports.one_inventory:GetAllItemDefinitions()
    -- rebuild your cached list here
end)

Config

GetClientConfig

A copy of the shared, client-facing config table (locale, keybinds, appearance, gameplay, ...). Available on both the server and the client, and safe to expose: it carries no server-only keys.

exports.one_inventory:GetClientConfig()

Returns: table - a copy of the client-facing config. Mutating it does not affect the live config.

Safe to forward to a client (e.g. via TriggerClientEvent) or to read directly from a client script with the client-side GetClientConfig.

GetServerConfig

The server-only config table (log providers, webhooks, seed state, group permissions). Server-side only.

exports.one_inventory:GetServerConfig()

Returns: table - the server-only config.

Keep this server-side. It holds secrets (webhooks, log providers, ...) that must never reach a client. Use GetClientConfig for anything a client needs.

Runtime registration

Register definitions at runtime, in memory. These are never persisted: they live until one_inventory restarts, so the registering resource must re-register them on every startup. Both refuse a name already owned by a saved (database) definition.

Runtime definitions appear read-only in the admin panel, tagged with the resource that registered them, and vanish on an inventory restart.

CreateItemsDefinition

Register one or more item definitions at runtime.

exports.one_inventory:CreateItemsDefinition(items)
items
table required
A single item table, an array of item tables, or a { [name] = item } map.

Per-item fields:

name
string required
Item name.
label
string
Defaults to name.
weight
number
Grams. Defaults to 0.
description
string
image
string
useTime
number
consume
number
degrade
number
unique
boolean
Defaults to false. Set true to make the item non-stackable.
close
boolean
Close the inventory on use.

Returns: boolean - false if the name is already a saved definition.

exports.one_inventory:CreateItemsDefinition({
  name        = 'mystery_box',
  label       = 'Mystery Box',
  weight      = 500,
  description = 'Who knows what is inside.',
  unique      = true,
  close       = true,
})

CreateContainersDefinition

Register one or more container definitions at runtime. Same runtime semantics as CreateItemsDefinition: in-memory, never persisted, refused when a saved definition already owns the name.

exports.one_inventory:CreateContainersDefinition(containers)
containers
table required
A single container table, an array of container tables, or a { [name] = container } map.

Per-container fields:

name
string required
Container name.
label
string
Defaults to name.
weight
number
Grams. Defaults to 0.
slots
number
Defaults to 10.
maxWeight
number
Grams. Defaults to 10000.
image
string
allowlist
string[]
Item names allowed inside. Enables the allowlist automatically when non-empty.
blacklist
string[]
Item names blocked from being placed inside.
defaultItems
table[]
{ name, count, metadata } entries seeded into a brand-new instance of the container.
If a container instance's definition is missing when it loads (a runtime definition not yet re-registered after a restart), the instance survives as an orphan slot and self-heals with its contents intact the moment the definition is registered again.

Returns: boolean - false if the name is already a saved definition.

exports.one_inventory:CreateContainersDefinition({
  name      = 'evidence_bag',
  label     = 'Evidence Bag',
  weight    = 200,
  slots     = 5,
  maxWeight = 5000,
  blacklist = { 'evidence_bag' },
})

RegisterShop

Register a shop at runtime. Runtime shops have no world interaction: no marker, no target zone, no NPC ped, no blip. The registering script opens them itself with OpenInventory.

exports.one_inventory:RegisterShop(shopData)
name
string required
Shop name.
label
string
Defaults to name.
currency
string
Defaults to cash. One of cash, bank, black_money, or any item name as a custom currency.
coords
vector3
Optional. Nothing is drawn for it. Saved purely as a security check.
locations
table[]
Optional. Array form of coords for multiple proximity points.
jobs
table | string | string[]
Optional. Job restriction. A name -> minGrade map ({ police = 2, sheriff = 0 })
gangs
table | string | string[]
Optional. Same shape as jobs, for gangs.
licenses
string | string[]
Optional. A license name or an array of license names.
inventory
table[]
The shop's items. Each entry: { name, price, count, metadata?, jobs?, gangs?, licenses? }. A count of 0 is infinite stock. The per-item jobs / gangs / licenses fields use the same forms as the shop-level fields and restrict that single item (the rest of the shop stays open to everyone).
Setting any of jobs, gangs, or licenses automatically marks the shop restricted. The client-side OpenInventory enforces those restrictions (plus proximity to coords); the server-side OpenInventory is forced and bypasses them, so gate it yourself.

Returns: boolean - false if the name is already a saved definition.

exports.one_inventory:RegisterShop({
    name = 'blackmarket',
    label = 'Black Market',
    currency = 'black_money',
    coords = vec3(25.7, -1347.3, 29.5),
    jobs = { police = 2, sheriff = 0 },
    gangs = { ballas = 0 },
    licenses = { 'weapon' },
    inventory = {
        { name = 'lockpick', price = 250, count = 0 },
        -- restrict a single item to police rank 2+ (the rest of the shop is unrestricted)
        { name = 'weapon_pistol', price = 5000, count = 5, jobs = { police = 2 } },
    },
})

-- server-side (forced, bypasses proximity + restrictions; gate it yourself):
exports.one_inventory:OpenInventory(src, 'shop', 'blackmarket')

-- client-side (validates the shop's job/gang/license restrictions, plus
-- proximity to `coords` when one was registered):
exports.one_inventory:OpenInventory('shop', 'blackmarket')

RegisterItemButton

Add a right-click button to an item's context menu. This server-side variant runs fn server-side when the button is clicked, with the player's source in the payload. Available on the client too (where fn runs client-side, without source).

exports.one_inventory:RegisterItemButton(itemName, label, fn)
itemName
string required
Item the button is shown on.
label
string required
Button text in the right-click menu.
fn
function required
Handler called with a single payload table (see below) when the button is clicked.

The fn payload (server side):

payload.source
number
Server id of the player who clicked. Server side only.
payload.slot
number
Slot the item sits in.
payload.item
string
Item name.
payload.count
number
Stack count.
payload.metadata
table
The slot's metadata.
payload.label
string
The item's label (not the button's).
payload.description
string
The item's description (not the button's).
Buttons are in memory only: they are not persisted, so re-register them on every resource restart. Clicking a button only runs its handler. It never uses or consumes the item.

Returns: boolean - false on invalid input or an unknown item.

exports.one_inventory:RegisterItemButton('water', 'Drink Water', function(payload)
    -- runs server-side; payload.source is the player who clicked
    print(('player %s drank from slot %s'):format(payload.source, payload.slot))
end)

Persistence

SaveInventory

Flush an inventory to the database immediately.

exports.one_inventory:SaveInventory(inv)
inv
string | number required
Inventory to flush. See Inventory identifiers.

Returns: boolean.


SaveAllInventories

Flush every loaded inventory to the database: players, stashes, drops, vehicle trunks, vehicle gloveboxes, and dumpsters.

exports.one_inventory:SaveAllInventories()

Returns: boolean.

Hooks

RegisterHook

Subscribe to a beforeX cancellable hook. See Hooks for the full list of hook names, payloads, and the post-hook event every registration also gets.

local id = exports.one_inventory:RegisterHook(event, fn, options)
event
string required
Hook name (e.g. beforeItemAdd).
fn
function
function(payload): boolean?. Return false to cancel; mutate payload fields to change them. May be omitted (nil) when options is set, for a post-events-only registration that never gates the action.
options
table
Optional filters: print, itemFilter, inventoryFilter, typeFilter. See Filters.

Returns: number - hook id; pass to RemoveHook to unsubscribe.


RemoveHook

Unsubscribe a previously-registered hook. Scoped to the calling resource: it can only remove hooks that resource registered.

exports.one_inventory:RemoveHook(id)
id
number
Hook id returned by RegisterHook. Omit (nil) to remove every hook registered by the calling resource.
Hooks are also auto-removed when the resource that registered them stops.

Returns: boolean - true if at least one hook was removed.

Open / force-open

OpenInventory

Server-forced open. Routes the call to the target client and bypasses every security check the client-side OpenInventory would normally enforce (distance, lock, in-vehicle, access restrictions, identifier match).

The user can still fully interact with whatever is opened: move items, buy from a forced shop, craft at a forced bench, and so on. The client-side OpenInventory export preserves all these checks; only this server export is forced.

exports.one_inventory:OpenInventory(source, invType, data)
source
number required
Server ID of the target client to open on.
invType
string required
One of stash, shop, crafting, drop, vehicle:trunk, vehicle:glovebox, player, license.
data
string | number | table required
Identifier shorthand or full data table - meaning varies by invType (see below).

Returns: boolean - true if the open event was dispatched, false on bad input.

container and dumpster are not supported here. Containers open from inside an inventory; dumpsters open via the world interaction loop.

Data fields (per invType)

invTypeData
stash{ id, owner?, slots?, maxWeight?, label?, groups? } - slots / maxWeight apply on auto-create AND live-resize
shop'<shop name>'
crafting'<bench name>'
drop'<drop id>'
vehicle:trunk<vehicle netId>
vehicle:glovebox<vehicle netId>
player<target server id>
license'<license name>'

Examples

The owner field controls how the stash contents are isolated. groups optionally gates access by job. slots, maxWeight, and label apply on auto-create AND resize an already-loaded stash live, so you can grow or shrink a stash from a script without restarting it.

ownerFlavourBehaviour
omit / falseSharedOne bucket. Everyone with access sees the same contents.
truePer-playerPer-opener private bucket, keyed automatically by the opener's identifier.
'<identifier>'OwnedForced owner identifier - server bypasses the ownership check.
exports.one_inventory:OpenInventory(source, 'stash', { id = 'evidence_locker' })

exports.one_inventory:OpenInventory(source, 'stash', {
  id    = 'personal_storage',
  owner = true,
})

exports.one_inventory:OpenInventory(source, 'stash', {
  id     = 'police_armory',
  groups = { { name = 'police', minGrade = 0 } },
})

-- Auto-creates a 100-slot warehouse OR live-resizes one that already exists.
exports.one_inventory:OpenInventory(source, 'stash', {
  id        = 'warehouse',
  label     = 'Warehouse',
  slots     = 100,
  maxWeight = 200000,
})

Drops

CreateDrop

Spawn a ground drop at coords pre-populated with items.

exports.one_inventory:CreateDrop(coords, items, options)
coords
vector3 | table required
World coordinates { x, y, z } for the drop.
items
table[] required
Array of { name, count?, metadata? }.
options
table
Optional. { instance = number } to scope the drop to a routing bucket.

Returns: string | false - drop id, or false on failure.


DropInventory

Dump a player's entire inventory into a ground drop at their coords, then clear it.

exports.one_inventory:DropInventory(inv)
inv
string | number required
Player to dump. Non-player inventories return false.

Returns: string | false - drop id, or false if the inventory is empty / can't be dumped.

Inspect, confiscate, restore

InspectInventory

Open a read-only view of another player's inventory on the inspector's client. Skips the distance gate.

exports.one_inventory:InspectInventory(inv, target)
inv
string | number required
Inspecting player. Non-player inventories return false.
target
string | number required
Target player to inspect. Non-player inventories return false.

Returns: boolean.


ConfiscateInventory

Move a player's inventory into DB escrow and clear it.

exports.one_inventory:ConfiscateInventory(inv)
inv
string | number required
Player to confiscate. Non-player inventories return false.

Returns: boolean.


RestoreInventory

Restore a previously-confiscated inventory from DB escrow back onto the player.

exports.one_inventory:RestoreInventory(inv)
inv
string | number required
Player to restore. Non-player inventories return false.

Returns: boolean.

Vehicles

UpdateVehiclePlate

Migrate trunk + glovebox storage rows from an old plate to a new plate.

exports.one_inventory:UpdateVehiclePlate(oldPlate, newPlate)
oldPlate
string required
Plate to migrate storage from.
newPlate
string required
Plate to migrate storage to.

Returns: boolean.

Weapons

DisarmPlayer

Unequip the player's currently-equipped weapon. The item stays in the inventory.

exports.one_inventory:DisarmPlayer(inv)
inv
string | number required
Player to disarm. Non-player inventories return false.

Returns: boolean.


RemoveWeapons

Remove every weapon-typed item from the player's inventory and disarm them.

exports.one_inventory:RemoveWeapons(inv)
inv
string | number required
Player to strip. Non-player inventories return false.

Returns: boolean.