Developer

4 min readUpdated Today

Overview

ML Random Cloth exposes two client exports (usePack, useCustomPack) used by item systems and two server-side net events that perform the validated give (ml_random_cloth:server:packOpened, ml_random_cloth:server:customPackOpened). There are no server exports and no client-facing callbacks. All framework and inventory calls go through ml_bridge.

Client Exports

Both exports are called by an item use through ox_inventory: standard packs use usePack and custom packs use useCustomPack. Both take the data table that the inventory passes on item use.

usePack

lua
1exports['ml_random_cloth']:usePack(data)

usePack(data) handles the 15 standard packs. It reads data.name, strips the pack_ prefix to get the clothing type, rolls a random drawable and texture on the local ped, runs the progress bar, then triggers the server to give the item. Wire it in ox_inventory with client = { export = 'ml_random_cloth.usePack' } on each pack_* item.

  • data (table, required): the item-use payload. Must contain data.name, for example pack_jacket.

useCustomPack

lua
1exports['ml_random_cloth']:useCustomPack(data)

useCustomPack(data) handles a pack defined in Config.CustomPacks. It looks up the pack by data.name, and depending on giveAll rolls one or all item types from the pack, runs the progress bar, then triggers the server. Wire it in ox_inventory with client = { export = 'ml_random_cloth.useCustomPack' } on each custom pack item.

  • data (table, required): the item-use payload. data.name must match a key in Config.CustomPacks.

Events

ml_random_cloth:server:packOpened (server, net)

lua
1TriggerServerEvent('ml_random_cloth:server:packOpened', packType, meta)

Fired by the client after the standard-pack progress bar completes. packType is the clothing type, for example jacket or bag and meta is the rolled { drawable, texture, sexRaw }. The server validates the type against Config.ClothingItems, applies the 3 second cooldown, confirms the player holds pack_<type>, sanitizes the metadata, checks carry space, removes the pack, then gives the clothing item with Bridge.GiveItem.

ml_random_cloth:server:customPackOpened (server, net)

lua
1TriggerServerEvent('ml_random_cloth:server:customPackOpened', packName, itemsList)

Fired by the client after a custom-pack progress bar completes. packName is the pack key, itemsList is an array of { type, meta } entries. The server re-validates every entry: the type must belong to the pack, no duplicate types, metadata is sanitized, and for keyed packs the drawable must be in the pack's allowed list for that gender. It enforces the expected item count for giveAll packs, checks carry space for all items, removes the pack, then gives each item.

How a Pack Gives Clothing

Standard pack:

  1. Player uses pack_jacket. ox_inventory calls the usePack client export.
  2. The client strips pack_ to get jacket, counts drawable and texture variations for that type on the player ped, removes excluded drawables and the default-outfit drawable, and picks a random drawable plus texture. For pants and jacket the texture pool is capped at 3.
  3. The progress bar runs for Config.Progress.OpenDuration with a PROP_HUMAN_PARKING_METER scenario.
  4. On completion the client triggers ml_random_cloth:server:packOpened with the rolled metadata.
  5. The server validates ownership, cooldown, carry space, removes the pack, and calls Bridge.GiveItem(src, packType, 1, meta). ml_clothing receives the item and enriches bag metadata (bag id, cols, rows, weight) through its own create hook.

Custom pack:

  1. The pack item calls the useCustomPack export on use, wired in ox_inventory with client = { export = 'ml_random_cloth.useCustomPack' }.
  2. The client rolls one type or all types depending on giveAll, using the pack's curated drawable lists for keyed packs or full random for string-array packs.
  3. The progress bar runs, then the client triggers ml_random_cloth:server:customPackOpened with the item list.
  4. The server re-validates each drawable against the pack definition, checks carry space, removes the pack, and gives each item with Bridge.GiveItem.
No server exports

This resource does not register any server-side exports. All server work happens inside the two net-event handlers above. Integrate by giving players the pack items, not by calling a server export.

Server is authoritative but trusts the rolled drawable within limits

The client rolls the drawable and texture and sends them to the server. The server sanitizes types, floors numeric metadata, enforces gender, ownership, cooldown, and carry space, and for keyed custom packs rejects any drawable not in the pack's allowed list. Standard packs and legacy string-array packs do not re-verify the specific drawable server-side, so the trust boundary for those is the sanitized numeric metadata plus item ownership.