GKSHOP
GKSPHONE V2Configuration

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/config.lua
Config.InventoryScript   = "my-inventory"
Config.TabletItemRequire = true
Config.TabletItemName    = "tablet"
ValueBehaviour
autoox_inventory if it is running, otherwise none
ox_inventoryThe built-in adapter
noneNo item check. Blocks opening when TabletItemRequire is true
anything elseYour adapter, guarded on that exact string

2. Create two files

gks-tablet/client/inventory/my-inventory.lua
gks-tablet/server/inventory/my-inventory.lua

fxmanifest.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 end

3. Client

client/inventory/my-inventory.lua
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

server/inventory/my-inventory.lua
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
end

HasTabletItem 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
end

Stash 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 clientrequired
HasTabletItem(source) on the serverrequired
UseTabletItem exportif your inventory calls exports
Item-removed handlerso the tablet closes when the item is dropped
RegisterStash / OpenStashonly for MDT case stashes

Troubleshooting

SymptomCause
Tablet never opensHasTabletItem missing or returning false on the server
Opens with no itemConfig.TabletItemRequire is false
Stays open after dropping the itemNo inventory-change handler on the client
Using the item does nothingUseTabletItem unreachable, and the framework fallback did not apply
Case stash does nothingRegisterStash returned false, or the job groups don't match Config.Jobs.Police

On this page