๐ ๏ธ 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
- Download this resource's files
- Rename qb-inventory-rework to qb-inventory
- delete your old inventory and replace with
qb-inventoryrework
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
},