5Mdev
OverviewQBCorev2.5

๐Ÿ› ๏ธ Installation QB INVENTORY REWORK

QB Inventory Rework is a complete replacement for the default QBCore inventory, designed to provide a more immersive and functional experience for players.

By Max ยท reviewed by Max ยท tested 2026-08-20

Unofficial community documentation. 5mdev is not AP Code and does not distribute paid files or license keys โ€” always buy or download from the official source below.

๐Ÿ› ๏ธ Installation

Follow these steps very carefully to ensure a smooth installation.

Step 1: Download & Place the Resource

  1. Download this resource's files
  2. Rename qb-inventory-rework to qb-inventory
  3. delete your old inventory and replace with qb-inventory rework

Step 2: Modify qb-core

๐Ÿšจ IMPORTANT: Always create a backup of any file you are about to edit!

You need to edit the qb-core/server/player.lua file to integrate the money-as-an-item system. This only enables the money side of it โ€” Config.CashAsItem in config/config.lua must also be set to true, or none of this branch ever runs (see Configuration).

A. Add the Cash-as-Item Branch to the Money Functions

Find function Player:AddMoney(moneytype, amount, reason) and insert the cash-as-item branch right after the existing nil/negative-amount guard clauses (before the function does its normal balance math). Do the same for RemoveMoney, SetMoney, and GetMoney:

--------------------------EDITED BY APCODE START--------------------------
function Player:AddMoney(moneytype, amount, reason)
    -- ...keep your existing guard clauses above this line...

    if moneytype == 'cash' and GetResourceState('qb-inventory') ~= 'missing' and exports['qb-inventory']:IsCashAsItem() then
        if not exports['qb-inventory']:AddCash(self.PlayerData.source, amount, reason) then return false end
        self.PlayerData.money.cash = exports['qb-inventory']:GetItemCount(self.PlayerData.source, 'cash') or 0
        if not self.Offline then
            self:UpdateClient('money', self.PlayerData.money)
            TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'AddMoney (as item)', 'lightgreen', '**' .. self.PlayerData.name .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (cash) added, reason: ' .. reason, amount > 100000)
            TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, false)
            TriggerClientEvent('QBCore:Client:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'add', reason)
            TriggerEvent('QBCore:Server:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'add', reason)
        end
        return true
    end

    -- ...your existing balance-update code continues unchanged below...
end

function Player:RemoveMoney(moneytype, amount, reason)
    -- ...keep your existing guard clauses above this line...

    if moneytype == 'cash' and GetResourceState('qb-inventory') ~= 'missing' and exports['qb-inventory']:IsCashAsItem() then
        if not exports['qb-inventory']:RemoveCash(self.PlayerData.source, amount, reason) then return false end
        self.PlayerData.money.cash = exports['qb-inventory']:GetItemCount(self.PlayerData.source, 'cash') or 0
        if not self.Offline then
            self:UpdateClient('money', self.PlayerData.money)
            TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'RemoveMoney (as item)', 'red', '**' .. self.PlayerData.name .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (cash) removed, reason: ' .. reason, amount > 100000)
            TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, true)
            TriggerClientEvent('QBCore:Client:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'remove', reason)
            TriggerEvent('QBCore:Server:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'remove', reason)
        end
        return true
    end

    -- ...your existing DontAllowMinus / balance-update code continues unchanged below...
end

function Player:SetMoney(moneytype, amount, reason)
    -- ...keep your existing guard clauses above this line...

    if moneytype == 'cash' and GetResourceState('qb-inventory') ~= 'missing' and exports['qb-inventory']:IsCashAsItem() then
        local currentCash = exports['qb-inventory']:GetItemCount(self.PlayerData.source, 'cash') or 0
        local difference  = amount - currentCash
        local success     = true
        if difference > 0 then
            success = exports['qb-inventory']:AddItem(self.PlayerData.source, 'cash', difference, nil, {}, 'setmoney_command')
        elseif difference < 0 then
            success = exports['qb-inventory']:RemoveItem(self.PlayerData.source, 'cash', math.abs(difference), nil, 'setmoney_command')
        end
        if not success then return false end
        local newTotalCash = exports['qb-inventory']:GetItemCount(self.PlayerData.source, 'cash') or 0
        self.PlayerData.money.cash = newTotalCash
        if not self.Offline then
            self:UpdateClient('money', self.PlayerData.money)
            TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'SetMoney (as item)', 'green', '**' .. self.PlayerData.name .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** cash set to $' .. newTotalCash .. ', reason: ' .. reason)
            TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, math.abs(difference), difference < 0)
            TriggerClientEvent('QBCore:Client:OnMoneyChange', self.PlayerData.source, moneytype, newTotalCash, 'set', reason)
            TriggerEvent('QBCore:Server:OnMoneyChange', self.PlayerData.source, moneytype, newTotalCash, 'set', reason)
        end
        return true
    end

    -- ...your existing balance-set code continues unchanged below...
end

function Player:GetMoney(moneytype)
    if not moneytype then return false end
    moneytype = moneytype:lower()

    if moneytype == 'cash' and GetResourceState('qb-inventory') ~= 'missing' and exports['qb-inventory']:IsCashAsItem() then
        local cashCount = exports['qb-inventory']:GetItemCount(self.PlayerData.source, 'cash') or 0
        if self.PlayerData.money.cash ~= cashCount then
            self.PlayerData.money.cash = cashCount
        end
        return cashCount
    end

    return self.PlayerData.money[moneytype]
end
--------------------------EDITED BY APCODE END--------------------------

B. Update the CheckPlayerData Function

Still in qb-core/server/player.lua, find the function QBCore.Player.CheckPlayerData. Do not delete the whole function โ€” some forks add their own logic in there (job default-duty handling, custom defaults, etc.), and wiping it out will silently regress those features. Instead, find the block that loads the inventory. It will look something like this:

if GetResourceState('qb-inventory') ~= 'missing' then
    PlayerData.items = exports['qb-inventory']:LoadInventory(PlayerData.source, PlayerData.citizenid)
end

(it may be gated with an extra not Offline and ... condition too โ€” keep whatever guard your version already has) and insert the cash sync right after the LoadInventory line, inside the same if block:

--------------------------EDITED BY APCODE START--------------------------
if GetResourceState('qb-inventory') ~= 'missing' then
    PlayerData.items = exports['qb-inventory']:LoadInventory(PlayerData.source, PlayerData.citizenid)
    if exports['qb-inventory']:IsCashAsItem() then
        local cashInInventory = 0
        if PlayerData.items then
            for _, item in pairs(PlayerData.items) do
                if item and item.name == 'cash' then
                    cashInInventory = cashInInventory + item.amount
                end
            end
        end
        PlayerData.money.cash = cashInInventory
    end
end
--------------------------EDITED BY APCODE END--------------------------

This ensures the player's inventory โ€” and their synced cash balance โ€” is loaded correctly when they join the server.

Step 3: Add Cash Item to qb-core/shared/items.lua

Only needed if you're enabling cash-as-item (Step 2 + Config.CashAsItem = true).

['cash'] = {
    name = 'cash',
    label = 'Cash',
    weight = 0,
    type = 'item',
    image = 'cash.png',
    unique = false,
    useable = false,
    shouldClose = false,
    description = 'Don\'t spend it all in one place.'
},

Step 4: Add Decay Rate to Food and Drinks

To make food and drinks perishable, you need to add a decay rate to them. Open qb-core/shared/items.lua and for every food and drink item, add the following line inside its definition:

decayrate = 86400.0

EXAMPLE :

['sandwich'] = {
    name = 'sandwich',
    label = 'Sandwich',
    weight = 200,
    type = 'item',
    image = 'sandwich.png',
    unique = false,
    useable = true,
    shouldClose = true,
    description = 'Nice bread for your stomach',
    decayrate = 86400.0
},