One Studios
Guides

Usable Items

Bind actions to items so they "do something" when used.

There are three ways to make an item "do something" when a player uses it. Pick the tab for how your other resources are written.

Creating Usables

Recommended. Create an export or event on your own resource, then bind its name into the item's serverExport / clientExport / serverEvent / clientEvent field in the admin panel item editor.

The bound value is a resource.functionName string (for exports) or an event name (for events). In the admin panel item editor, fill the serverExport / clientExport / serverEvent / clientEvent field with that string, e.g. myresource.myItem.

Server-side export - params come from the item-use flow. Returning false cancels the use (skips the client pipeline, consume, status and durability):

-- in myresource (DB field: serverExport = "myresource.myItem")
exports('myItem', function(src, itemName, slot, metadata)
  -- do server-side stuff
  -- return false to cancel the use
end)

Server-side event - same params. Fire-and-forget: the return value is ignored, so a server event cannot cancel the use.

-- DB field: serverEvent = "myresource:myItem"
RegisterNetEvent('myresource:myItem', function(src, itemName, slot, metadata)
  -- do server-side stuff
end)

Client-side export - runs after the progress bar / animation completes. If the progress bar is cancelled, this never runs and the use is cancelled server-side too:

-- DB field: clientExport = "myresource.myItem"
exports('myItem', function(itemName, slot, metadata)
  -- do client-side stuff
end)

Client-side event - same params, fired right after the client export:

-- DB field: clientEvent = "myresource:myItem"
AddEventHandler('myresource:myItem', function(itemName, slot, metadata)
  -- do client-side stuff
end)

How one_inventory decides which handler to run

When an item is used, one_inventory first checks whether the item has any one_inventory-side use config set in the admin panel. That means any of:

serverExport, clientExport, serverEvent, clientEvent, close, consume, notification, animationId, propId, the hunger/thirst status effects (statusHunger, statusThirst), or any of the disable* flags (disableMove, disableCar, disableCombat, disableMouse, disableSprint).

Has use config → one_inventory runs our pipeline: fire the configured server export/event, send to the client, play the animation, run the client export/event, apply status effects, consume, drain durability. Framework-registered callbacks do not fire.
No use config → one_inventory falls through to the ESX/QB-registered callback for that item.

If an item is configured both ways (registered through ESX/QB and given a use field in our panel), our flow wins and one_inventory prints a one-time warning so you can spot it.

Controlling the full use flow

For full control, combine the primitives we already ship into a three-stage pattern:

  1. Gate the use before anything runs with the beforeItemUse hook (return false to cancel):
    exports.one_inventory:RegisterHook('beforeItemUse', function(payload)
        if not isAllowed(payload.source) then return false end
    end)
    
  2. Side-effects during the use with the bound serverExport / clientExport.
  3. Post-use cleanup / logging with the onItemUsed event:
    AddEventHandler('one_inventory:onItemUsed', function(payload)
        -- payload: { source, item, slot, metadata } on the server
    end)
    
onItemUsed fires on the server (payload { source, item, slot, metadata }) and on the client (payload { item, slot, metadata }, no source). See Server events and Client events.

Coming from ox_inventory?

ox-style (event, item, inventory, slot, data) use callbacks are not backwards compatible. Rewrite the handler against the signatures shown in the one_inventory tab above, it's about five lines.

For everything else (data reads like AddItem, RemoveItem, Search, useItem, ...), the ox exports keep working through our compatibility layer. See Backwards Compatibility.