Developer

8 min readUpdated Today

Developer

ML Inventory keeps the ox_inventory API as it is and adds a few entry points of its own. ML Clothing has its own exports plus the open/ files you edit in place. Only symbols that exist in the source are listed here.

The ox_inventory API is unchanged

The resource answers to the name ox_inventory. Every export, event and hook of your ox_inventory install keeps working under the same name with the same arguments, so no script of yours needs an edit.

lua
1local count = exports.ox_inventory:GetItemCount(source, 'water')

The additions below are reached the same way.

Hook bus

Any resource can register a handler. Handlers are dropped when the resource that registered them stops, so a restart during development leaves nothing behind.

lua
1exports.ox_inventory:mlRegisterHook('beforeItemDelete', function(ctx)
2    if ctx.itemName == 'evidence_bag' then
3        return 'Evidence cannot be destroyed'
4    end
5end)

The handler is a function, or a table { fn = handler, priority = 50 }. Lower priority runs first and the default is 50. The call returns an id for mlUnregisterHook(name, id).

Three ways a hook runs

  • mlRunHook(name, context): every handler runs. A handler returning false stops the action; returning a string stops it and hands the string back as the reason.
  • mlEmitHook(name, context): every handler runs and return values are ignored.
  • mlTransformHook(name, context): a handler returning a table replaces the context for the handlers after it and for the caller. Returning false cancels.

Hook points

  • beforeItemDelete on the server, run: source, inventoryId, slot, itemName, count, metadata. Returning false or a string blocks the deletion.
  • afterItemDelete on the server, emit: source, inventoryId, slot, itemName.
  • afterInventoryOpen on the client, emit: inventory.
  • afterInventoryClose on the client, emit, with no fields.

Turning features off for one player

lua
1exports.ox_inventory:mlDisableFeature(source, 'give', true)

The features are grid, clothing, loot, give and admin. Read the current state with mlIsFeatureDisabled(source, feature) and cover all five at once with mlDisableAllFeatures(source, disabled). The block is dropped when the player leaves.

Columns of a single inventory

lua
1exports.ox_inventory:mlSetInventoryCols('gang_stash_1', 5)

Sets the grid width of one inventory by id. Without an override, the player grid uses playerCols, a ground drop uses dropCols, anything else uses secondaryCols, and a stash or container takes a width from its slot count.

Registering a stash with a width

RegisterStash takes the width in two ways. Pass the slots as a table:

lua
1exports.ox_inventory:RegisterStash('gang_stash_1', 'Gang Stash', { slots = 30, cols = 5 }, 100000)

Or, when the call already passes an instance as the ninth argument, the eighth is the width:

lua
1exports.ox_inventory:RegisterStash('gang_stash_1', 'Gang Stash', 30, 100000, nil, nil, nil, 5, instanceId)

A call with eight arguments keeps the stock meaning, where the eighth argument is the instance. CreateTemporaryStash reads cols from its properties table.

Loot stashes

lua
1local id = exports.ox_inventory:OpenLootStash(source, 'stash', { id = 'crate_01' }, { persistent = true })

Opens an inventory for one player as a loot container: what is inside stays hidden until the player uncovers it. The fourth argument is passed on to the interface; persistent is the field the server itself checks, and it is required before a loot config is accepted on a stored inventory. On a temporary inventory it is not needed. The call returns the inventory id.

ML Clothing server exports

Wear and durability

lua
1exports.ml_clothing:GetWornDurability(src, slot)

Returns the durability value from the item metadata in the given inventory slot, or nil if the slot is empty or has no metadata.

lua
1exports.ml_clothing:IsGearBroken(src, slot)

Returns true if the worn piece in that slot is currently flagged broken, otherwise false.

lua
1exports.ml_clothing:RepairGear(src, slot, amount)

Repairs the worn piece in that slot by amount, clamped 1 to 100 and defaulting to 100. Returns false if the arguments are not numbers or the slot is not wear managed, otherwise the result of the repair.

Equipment stashes

lua
1exports.ml_clothing:RegisterEquipmentStash(stashType, uniqueId, slots, maxWeight, cols)

stashType is 'plateCarrier' or 'bag'. The id is built from the matching prefix in Config.Stash plus uniqueId. Returns the full stash id. cols is optional.

lua
1exports.ml_clothing:GetEquipmentStashId(stashType, uniqueId)

Returns the stash id that RegisterEquipmentStash would produce for the same arguments, without registering it.

Reserved slots

lua
1exports.ml_clothing:GetReservedSlots()

Returns the sorted list of clothing slot numbers, 11 to 25. Use it to keep other scripts from writing into a reserved slot.

ML Clothing client exports

Appearance

lua
1exports.ml_clothing:getCurrentAppearance()

Returns the current ped appearance snapshot, components and props.

lua
1exports.ml_clothing:applyAppearance(appearanceData)

Applies an appearance table to the local ped, setting components and props.

lua
1exports.ml_clothing:saveAppearance()

Captures the current ped appearance and sends it to the server to persist.

lua
1exports.ml_clothing:syncFromNUI(appearanceData)

Sends an appearance table to the server as a new outfit to turn into inventory items. This is the call to add inside the appearance script wherever an outfit is saved.

lua
1exports.ml_clothing:syncFromPed()

Reads the live ped components and props and syncs them into inventory items. Use it instead of syncFromNUI when the appearance data is not at hand or its format has no adapter.

lua
1exports.ml_clothing:clearSkin()

Resets the ped clothing components to their default state.

Vest and plate carrier

lua
1exports.ml_clothing:useVest(item, data)

Equips or removes the plate carrier. Plays the tie animation, registers the carrier if needed, and sets ped armor from the sum of inserted plate health, capped at 100.

Give mode and loot feedback

lua
1exports.ml_clothing:openGiveMode(data)

Starts hand item to player targeting. The player aims at someone nearby and confirms to give the item.

lua
1exports.ml_clothing:lootTrapEffect()

Plays a trap reaction on the local ped: animation, screen effect, sound and a small amount of damage.

lua
1exports.ml_clothing:PlayLootSound(data)

Plays a named loot sound. data is an event name string, or a table with an event field. Recognized events include container_open, scan_tick, slot_unlock, reveal_common, reveal_uncommon, reveal_rare, reveal_epic, reveal_legendary and loot_all.

Preview ped positioning

lua
1exports.ml_clothing:OnPedScreenPosition(data)
2exports.ml_clothing:OnPedZoom(data)
3exports.ml_clothing:OnTargetPedScreenPosition()

Drive the placement and zoom of the preview ped shown next to the inventory. OnTargetPedScreenPosition is a stub that does nothing.

Admin gizmo

lua
1exports.ml_clothing:UseGizmo(...)
2exports.ml_clothing:StopGizmo()
3exports.ml_clothing:IsGizmoActive()

Start, stop and query the placement gizmo used by the admin panel.

Owner hooks

These live in open/ and are meant to be edited. ML Clothing calls them at fixed points.

Server hooks (open/server.lua)

lua
1function OpenServer.PunishPlayer(source, reason) end
2function OpenServer.BeforeGiveItem(src, item, amount) end
3function OpenServer.OnActionComplete(src, actionType, data) end
4function OpenServer.OnGearBroken(src, itemName, slot, key) end
5function OpenServer.OnGearRepaired(src, slot) end
  • PunishPlayer: called when a suspicious action is detected. Put your ban, kick or log logic here. The default prints a debug line.
  • BeforeGiveItem: return true to allow or false to block, before an item is given. Defaults to true.
  • OnActionComplete: called after an action completes.
  • OnGearBroken: fired once when a worn piece reaches zero durability. The key is c:<component>:<drawable>:<texture> for components or p:<prop>:<drawable>:<texture> for props.
  • OnGearRepaired: fired when a worn piece is repaired back above zero.

Client hooks (open/client.lua)

lua
1function OpenClient.BeforeOpenUI(data) end
  • BeforeOpenUI: return true to let the interface open. Defaults to true.

Shared hooks (open/shared.lua)

lua
1function OpenHandlers.OnPlayerAction(src, data) end
2function OpenHandlers.ValidateAction(src, actionType) end
  • OnPlayerAction and ValidateAction: return true to allow the action. Both default to true.
Notifications

Notifications from ML Clothing are sent through ml_bridge, which picks the notification system your server runs.

Appearance adapters (open/adapters/)

One file per appearance format. Two ship with the resource: standard.lua and bl_appearance.lua. Each defines a function on Config.DataAdapters that takes the appearance data and returns entries of { type, id, drawable, texture }, where type is component or prop. The server tries the adapters in turn and the first one that returns entries wins. To support another format, add a file to the folder, then run refresh and restart the resource so the new file is picked up.

State bag

A worn out piece is exposed through a player state bag so other scripts can react.

lua
1local broken = LocalPlayer.state.ml_clothingBroken

ml_clothingBroken holds the broken worn drawables, keyed c:<component>:<drawable>:<texture> for components and p:<prop>:<drawable>:<texture> for props. ml_radiation reads it to drop the protection of a worn out mask or suit when its RespectWear option is on.

Examples

lua
1exports.ox_inventory:mlRegisterHook('beforeItemDelete', function(ctx)
2    if ctx.itemName ~= 'evidence_bag' then return end
3
4    return 'Evidence cannot be destroyed'
5end)
lua
1local uniqueId = 'trunk_' .. plate
2local slots, maxWeight, cols = 20, 40000, 5
3
4local stashId = exports.ml_clothing:RegisterEquipmentStash('bag', uniqueId, slots, maxWeight, cols)
lua
1local reserved = exports.ml_clothing:GetReservedSlots()
2
3local function isReserved(slot)
4    for i = 1, #reserved do
5        if reserved[i] == slot then return true end
6    end
7
8    return false
9end
lua
1if exports.ml_clothing:IsGearBroken(src, slot) then
2    exports.ml_clothing:RepairGear(src, slot, 100)
3end
open/server.lua
1function OpenServer.OnGearBroken(src, itemName, slot, key)
2
3end
Inventory Developer, FiveM Docs | Micio Mods