Custom Inventory
Write an adapter for an inventory other than ox_inventory, modelled on the built-in one.
Needs Lua experience. We can't write or debug the adapter for you.
The tablet ships one inventory adapter, ox_inventory. Anything else means writing a pair of files. The built-in adapter is short and is the reference below — yours has the same shape with different exports.
You only need this at all if Config.TabletItemRequire = true, or if you want MDT case evidence stashes.
1. Set the config
Config.InventoryScript = "my-inventory"
Config.TabletItemRequire = true
Config.TabletItemName = "tablet"| Value | Behaviour |
|---|---|
auto | ox_inventory if it is running, otherwise none |
ox_inventory | The built-in adapter |
none | No item check. Blocks opening when TabletItemRequire is true |
| anything else | Your adapter, guarded on that exact string |
2. Create two files
gks-tablet/client/inventory/my-inventory.lua
gks-tablet/server/inventory/my-inventory.luafxmanifest.lua already globs client/inventory/*.lua and server/inventory/*.lua, so both load on restart. Both folders are outside escrow.
Start each with the guard:
if Config.InventoryScript ~= "my-inventory" then return end3. Client
if Config.InventoryScript ~= "my-inventory" then return end
local itemName = Config.TabletItemName or "tablet"
--- Required. Does the local player carry the tablet?
--- @return boolean
function HasTabletItem()
return exports['my-inventory']:Search('count', itemName) > 0
end
--- Called when the player uses the item from their inventory.
exports("UseTabletItem", function(data, itemData)
TriggerEvent("gkstablet:client:useTabletItem")
end)
--- Close the tablet if the item leaves the inventory while it is open.
AddEventHandler('my-inventory:updateInventory', function()
if not Config.TabletItemRequire then return end
if not IsTabletOpen then return end
if not HasTabletItem() then
ItemTabletDeleted()
end
end)IsTabletOpen and ItemTabletDeleted are provided by the tablet — call them, don't define them.
Case evidence stash
Only needed if you use MDT case stashes. The tablet closes itself first so the inventory UI isn't drawn underneath:
RegisterNetEvent('gkstablet:client:inventory:openStash', function(stashId)
if not stashId or stashId == '' then return end
if ToggleTablet then ToggleTablet(false) end
Wait(150)
exports['my-inventory']:openInventory('stash', { id = stashId })
end)4. Server
if Config.InventoryScript ~= "my-inventory" then return end
local itemName = Config.TabletItemName or "tablet"
--- Required. Does this player carry the tablet?
--- @param source number
--- @return boolean
function HasTabletItem(source)
return exports['my-inventory']:Search(source, 'count', itemName) > 0
endHasTabletItem is the only required function. Without it the server cannot verify the item, and opening is refused whenever TabletItemRequire is on.
Case evidence stash
local registeredStashes = {}
--- Create the stash once, scoped to the police jobs
function RegisterStash(stashId, label)
if registeredStashes[stashId] then return true end
local groups = {}
for _, job in ipairs(Config.Jobs.Police or {}) do
groups[job] = 0
end
local ok = pcall(function()
exports['my-inventory']:RegisterStash(
stashId, label,
Config.CaseStash.slots or 50,
Config.CaseStash.maxWeight or 100000,
false, groups
)
end)
if not ok then return false end
registeredStashes[stashId] = true
return true
end
--- Called by the MDT when an officer opens a case stash
function OpenStash(source, stashId, label)
if not RegisterStash(stashId, label) then return false end
TriggerClientEvent("gkstablet:client:inventory:openStash", source, stashId)
return true
endStash settings come from Config.CaseStash in config/config.lua:
Config.CaseStash = {
slots = 50,
maxWeight = 100000, -- 100 kg
prefix = "gks_mdt_case_", -- stash ids are this plus the case id
}Usable items
You usually do not need to register the usable item yourself. When TabletItemRequire is on and the framework is ESX, QBCore or QBox, server/inventory/framework_usable.lua registers it through the framework already.
Write your own registration only if your inventory bypasses the framework entirely.
Checklist
Config.InventoryScript set to your adapter's name | |
| Both files guarded on that name | |
HasTabletItem() on the client | required |
HasTabletItem(source) on the server | required |
UseTabletItem export | if your inventory calls exports |
| Item-removed handler | so the tablet closes when the item is dropped |
RegisterStash / OpenStash | only for MDT case stashes |
Troubleshooting
| Symptom | Cause |
|---|---|
| Tablet never opens | HasTabletItem missing or returning false on the server |
| Opens with no item | Config.TabletItemRequire is false |
| Stays open after dropping the item | No inventory-change handler on the client |
| Using the item does nothing | UseTabletItem unreachable, and the framework fallback did not apply |
| Case stash does nothing | RegisterStash returned false, or the job groups don't match Config.Jobs.Police |

