docsresourcesQb Inventory

QB-Inventory - Advanced Inventory System

The qb-inventory resource provides a modern, drag-and-drop inventory system for QBCore servers, featuring weight management, item stacking, hotbar functionality, and extensive customization options.

Overview

QB-Inventory completely replaces the default GTA V inventory system with a sophisticated interface that supports item management, crafting, trading, and storage systems. The inventory features a grid-based layout with visual item representations and realistic weight constraints.

Key Features

  • Modern UI: Drag-and-drop grid-based interface
  • Weight System: Realistic item weights and carrying capacity
  • Hotbar Integration: Quick access slots for frequently used items
  • Item Stacking: Automatic stacking of similar items
  • Inventory Types: Player, vehicle, house, and custom storage inventories
  • Item Durability: Degradation system for weapons and tools
  • Crafting System: Built-in crafting interface and recipes
  • Trading System: Secure player-to-player item trading
  • Shop Integration: Compatible with various shop systems

Installation

Prerequisites

  • QBCore Framework
  • qb-target (for inventory interactions)
  • qb-weapons (for weapon durability)

Installation Steps

  1. Download the Resource
cd resources/[qb]
git clone https://github.com/qbcore-framework/qb-inventory.git
  1. Replace Core Inventory

    QB-Inventory replaces the default QBCore inventory system. Make sure to:

    • Remove or disable any other inventory resources
    • Update qb-core configuration to use qb-inventory
  2. Database Setup

-- Update items table structure
ALTER TABLE `player_items` ADD COLUMN `metadata` longtext DEFAULT '{}';
ALTER TABLE `player_items` ADD COLUMN `created` timestamp DEFAULT current_timestamp();
 
-- Create additional tables if needed
CREATE TABLE IF NOT EXISTS `stashitems` (
  `stash` varchar(255) NOT NULL,
  `items` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`items`)),
  PRIMARY KEY (`stash`)
);
 
CREATE TABLE IF NOT EXISTS `trunkitems` (
  `plate` varchar(255) NOT NULL,
  `items` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`items`)),
  PRIMARY KEY (`plate`)
);
 
CREATE TABLE IF NOT EXISTS `gloveboxitems` (
  `plate` varchar(255) NOT NULL,
  `items` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`items`)),
  PRIMARY KEY (`plate`)
);
  1. Add to server.cfg
ensure qb-inventory
  1. Restart Server
restart qb-inventory
⚠️

QB-Inventory must load after qb-core and before any resources that depend on inventory functions

Configuration

Basic Configuration

The main configuration file is located at config.lua:

Config = {}
 
-- General settings
Config.UseTarget = GetConvar('UseTarget', 'false') == 'true'
Config.MaxInventoryWeight = 120000 -- Maximum weight in grams
Config.MaxInventorySlots = 41
 
-- For detailed weight balancing across different item types and 
-- advanced metadata handling, see: https://fivemx.com/inventory-weight-tuning/
 
-- Hotbar configuration
Config.Hotbar = {
    slots = 5,
    keys = {
        [1] = {key = 'slot1', description = 'Use Item Slot 1'},
        [2] = {key = 'slot2', description = 'Use Item Slot 2'},
        [3] = {key = 'slot3', description = 'Use Item Slot 3'},
        [4] = {key = 'slot4', description = 'Use Item Slot 4'},
        [5] = {key = 'slot5', description = 'Use Item Slot 5'}
    }
}
 
-- Vehicle storage configuration
Config.VehicleLimit = {
    [0] = 38000,  -- Compacts
    [1] = 45000,  -- Sedans
    [2] = 65000,  -- SUVs
    [3] = 35000,  -- Coupes
    [4] = 40000,  -- Muscle
    [5] = 35000,  -- Sports Classics
    [6] = 30000,  -- Sports
    [7] = 25000,  -- Super
    [8] = 15000,  -- Motorcycles
    [9] = 50000,  -- Off-road
    [10] = 80000, -- Industrial
    [11] = 70000, -- Utility
    [12] = 60000, -- Vans
    [13] = 5000,  -- Cycles
    [14] = 85000, -- Boats
    [15] = 50000, -- Helicopters
    [16] = 75000, -- Planes
}
 
-- Trunk and glovebox configuration
Config.GloveboxLimit = 10000 -- Weight limit for gloveboxes
Config.TrunkLimit = Config.VehicleLimit -- Uses vehicle class limits
 
-- Durability settings
Config.ItemDurability = true
Config.DurabilityBlockedItems = {
    'phone',
    'money',
    'radio'
}

Item Configuration

Items are configured in shared/items.lua:

QBShared = QBShared or {}
QBShared.Items = {
    -- Weapons
    ['weapon_pistol'] = {
        ['name'] = 'weapon_pistol',
        ['label'] = 'Pistol',
        ['weight'] = 1000,
        ['type'] = 'weapon',
        ['ammotype'] = 'AMMO_PISTOL',
        ['image'] = 'weapon_pistol.png',
        ['unique'] = true,
        ['useable'] = false,
        ['description'] = 'A small firearm'
    },
    
    -- Consumables
    ['sandwich'] = {
        ['name'] = 'sandwich',
        ['label'] = 'Sandwich',
        ['weight'] = 200,
        ['type'] = 'item',
        ['image'] = 'sandwich.png',
        ['unique'] = false,
        ['useable'] = true,
        ['shouldClose'] = true,
        ['combinable'] = nil,
        ['description'] = 'Nice bread for your stomach'
    },
    
    -- Tools
    ['lockpick'] = {
        ['name'] = 'lockpick',
        ['label'] = 'Lockpick',
        ['weight'] = 300,
        ['type'] = 'item',
        ['image'] = 'lockpick.png',
        ['unique'] = false,
        ['useable'] = true,
        ['shouldClose'] = true,
        ['combinable'] = nil,
        ['description'] = 'Very useful if you lose your keys a lot'
    }
}

Crafting Configuration

Config.Crafting = {
    enabled = true,
    locations = {
        {coords = vector3(1275.55, -1710.46, 54.77), radius = 5.0},
        {coords = vector3(-330.40, -141.76, 39.01), radius = 3.0}
    }
}
 
Config.CraftingItems = {
    ['lockpick'] = {
        ['materials'] = {
            ['metalscrap'] = 22,
            ['plastic'] = 32,
        },
        ['amount'] = 1,
        ['points'] = 1,
        ['time'] = 15000, -- 15 seconds
    },
    ['repairkit'] = {
        ['materials'] = {
            ['metalscrap'] = 32,
            ['steel'] = 43,
            ['plastic'] = 61,
        },
        ['amount'] = 1,
        ['points'] = 3,
        ['time'] = 30000, -- 30 seconds
    }
}

API Reference

Client Exports

OpenInventory

Opens the inventory interface.

-- Open player inventory
exports['qb-inventory']:OpenInventory()
 
-- Open specific inventory type
exports['qb-inventory']:OpenInventory('trunk', 'ABC123')
exports['qb-inventory']:OpenInventory('stash', 'personalstash_123')

HasItem

Checks if player has a specific item.

-- Check for single item
local hasItem = exports['qb-inventory']:HasItem('phone')
 
-- Check for multiple items
local hasItems = exports['qb-inventory']:HasItem({'phone', 'money'}, true) -- true = need all items

GetItemCount

Gets the count of a specific item.

-- Get item count
local phoneCount = exports['qb-inventory']:GetItemCount('phone')
print("You have " .. phoneCount .. " phones")

Server Exports

AddItem

Adds an item to a player’s inventory.

-- Add basic item
exports['qb-inventory']:AddItem(source, 'phone', 1)
 
-- Add item with metadata
exports['qb-inventory']:AddItem(source, 'weapon_pistol', 1, false, {
    durability = 100,
    ammo = 12,
    serial = 'ABC123XYZ'
})

RemoveItem

Removes an item from a player’s inventory.

-- Remove basic item
exports['qb-inventory']:RemoveItem(source, 'phone', 1)
 
-- Remove specific item by slot
exports['qb-inventory']:RemoveItem(source, 'phone', 1, 5) -- slot 5

GetItemsByName

Gets all items of a specific name.

-- Get all phones in inventory
local phones = exports['qb-inventory']:GetItemsByName(source, 'phone')
for k, v in pairs(phones) do
    print("Phone in slot " .. v.slot .. " with " .. v.amount .. " quantity")
end

SetItemDurability

Sets the durability of an item.

-- Set weapon durability
exports['qb-inventory']:SetItemDurability(source, 'weapon_pistol', 75.5)

Events

Client Events

-- Inventory events
RegisterNetEvent('qb-inventory:client:openInventory', function(inventoryType, inventoryId)
    -- Handle inventory opening
end)
 
RegisterNetEvent('qb-inventory:client:closeInventory', function()
    -- Handle inventory closing
end)
 
-- Item events
RegisterNetEvent('qb-inventory:client:useItem', function(itemName, item)
    -- Handle item usage
end)
 
RegisterNetEvent('qb-inventory:client:itemBox', function(itemData, type)
    -- Handle item notifications (add/remove)
end)

Server Events

-- Item management
RegisterNetEvent('qb-inventory:server:addItem', function(itemName, amount, slot, info))
RegisterNetEvent('qb-inventory:server:removeItem', function(itemName, amount, slot))
 
-- Inventory actions
RegisterNetEvent('qb-inventory:server:openInventory', function(inventoryType, inventoryId))
RegisterNetEvent('qb-inventory:server:closeInventory', function())
 
-- Trading system
RegisterNetEvent('qb-inventory:server:tradeItems', function(targetId, items))

Usage Examples

Basic Item Management

-- Give starting items to new players
RegisterNetEvent('QBCore:Server:PlayerLoaded', function(Player)
    local src = Player.PlayerData.source
    
    -- Give basic items
    exports['qb-inventory']:AddItem(src, 'phone', 1)
    exports['qb-inventory']:AddItem(src, 'money', 500)
    exports['qb-inventory']:AddItem(src, 'id_card', 1, false, {
        citizenid = Player.PlayerData.citizenid,
        name = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname
    })
end)

Custom Inventory Slots

-- Create custom stash
RegisterNetEvent('housing:server:openStash', function(houseId)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    
    if Player then
        local stashName = 'house_' .. houseId
        exports['qb-inventory']:OpenInventory(src, 'stash', stashName, {
            maxweight = 50000,
            slots = 25
        })
    end
end)

Weapon Durability System

-- Weapon degradation on use
RegisterNetEvent('weapons:server:useWeapon', function(weaponName)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    local weapon = Player.Functions.GetItemByName(weaponName)
    
    if weapon and weapon.info.durability then
        local newDurability = weapon.info.durability - math.random(1, 5)
        
        if newDurability <= 0 then
            Player.Functions.RemoveItem(weaponName, 1, weapon.slot)
            TriggerClientEvent('QBCore:Notify', src, 'Your weapon broke!', 'error')
        else
            exports['qb-inventory']:SetItemDurability(src, weaponName, newDurability)
        end
    end
end)

Crafting System Integration

-- Custom crafting event
RegisterNetEvent('crafting:server:craftItem', function(itemName)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    local recipe = Config.CraftingItems[itemName]
    
    if recipe then
        local canCraft = true
        
        -- Check materials
        for material, amount in pairs(recipe.materials) do
            if not exports['qb-inventory']:HasItem(src, material, amount) then
                canCraft = false
                break
            end
        end
        
        if canCraft then
            -- Remove materials
            for material, amount in pairs(recipe.materials) do
                exports['qb-inventory']:RemoveItem(src, material, amount)
            end
            
            -- Add crafted item
            exports['qb-inventory']:AddItem(src, itemName, recipe.amount)
            TriggerClientEvent('QBCore:Notify', src, 'Successfully crafted ' .. itemName, 'success')
        else
            TriggerClientEvent('QBCore:Notify', src, 'Missing materials', 'error')
        end
    end
end)

Vehicle Storage Integration

-- Open vehicle trunk
RegisterNetEvent('qb-inventory:server:openTrunk', function(plate)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    
    if Player then
        exports['qb-inventory']:OpenInventory(src, 'trunk', plate, {
            maxweight = GetVehicleMaxWeight(plate),
            slots = 20
        })
    end
end)
 
-- Custom vehicle weight calculation
function GetVehicleMaxWeight(plate)
    local vehicle = GetVehicleByPlate(plate)
    if vehicle then
        local class = GetVehicleClass(vehicle)
        return Config.VehicleLimit[class] or 50000
    end
    return 50000
end

Trading System

-- Secure item trading
RegisterNetEvent('trading:server:offerTrade', function(targetId, items)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    local TargetPlayer = QBCore.Functions.GetPlayer(targetId)
    
    if Player and TargetPlayer then
        -- Validate items exist
        local validTrade = true
        for _, item in pairs(items) do
            if not exports['qb-inventory']:HasItem(src, item.name, item.amount) then
                validTrade = false
                break
            end
        end
        
        if validTrade then
            TriggerClientEvent('trading:client:receiveOffer', targetId, {
                from = src,
                items = items,
                player = Player.PlayerData.charinfo
            })
        end
    end
end)

Administrative Commands

Player Commands

  • /inv - Open inventory (if not using item)
  • /hotbar - Toggle hotbar visibility
  • /clearinv - Clear inventory (admin only)

Admin Commands

  • /giveitem [id] [item] [amount] - Give item to player
  • /removeitem [id] [item] [amount] - Remove item from player
  • /clearinventory [id] - Clear player’s inventory
  • /setweight [id] [weight] - Set player’s carrying capacity

Console Commands

# Give item to player
giveitem 1 phone 1
 
# Remove item from player
removeitem 1 phone 1
 
# Clear player inventory
clearinventory 1

Integration with Other Resources

qb-weapons Integration

Weapon attachment and ammo system:

-- Weapon with attachments
local weaponData = {
    durability = 100,
    ammo = 30,
    attachments = {
        {component = 'COMPONENT_AT_PI_FLSH', label = 'Flashlight'},
        {component = 'COMPONENT_PISTOL_CLIP_02', label = 'Extended Clip'}
    },
    serial = GenerateSerial()
}
 
exports['qb-inventory']:AddItem(source, 'weapon_pistol', 1, false, weaponData)

qb-shops Integration

Shop inventory management:

-- Shop purchase with inventory check
RegisterNetEvent('qb-shops:server:purchaseItem', function(itemName, amount, price)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    
    if Player.Functions.RemoveMoney('cash', price * amount) then
        exports['qb-inventory']:AddItem(src, itemName, amount)
        TriggerClientEvent('QBCore:Notify', src, 'Purchase successful', 'success')
    else
        TriggerClientEvent('QBCore:Notify', src, 'Insufficient funds', 'error')
    end
end)

qb-housing Integration

House storage system:

-- House stash access
RegisterNetEvent('qb-houses:server:openStash', function(houseId)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    
    if HasHouseAccess(Player.PlayerData.citizenid, houseId) then
        exports['qb-inventory']:OpenInventory(src, 'stash', 'house_' .. houseId, {
            maxweight = 500000,
            slots = 50
        })
    end
end)

Troubleshooting

Common Issues

Items Not Saving

Problem: Items disappear after server restart.

Solutions:

  1. Check database connection
  2. Verify table structure
  3. Check for inventory save errors in server console
-- Debug item saving
RegisterCommand('debuginv', function()
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    
    print("Player items count: " .. #Player.PlayerData.items)
    for slot, item in pairs(Player.PlayerData.items) do
        print("Slot " .. slot .. ": " .. item.name .. " x" .. item.amount)
    end
end, false)

Weight Issues

Problem: Can’t pick up items due to weight restrictions.

Solution:

-- Check current weight
RegisterCommand('weight', function()
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    local currentWeight = exports['qb-inventory']:GetCurrentWeight(src)
    local maxWeight = Config.MaxInventoryWeight
    
    print("Current weight: " .. currentWeight .. "/" .. maxWeight)
    TriggerClientEvent('QBCore:Notify', src, 'Weight: ' .. math.floor(currentWeight/1000) .. 'kg / ' .. math.floor(maxWeight/1000) .. 'kg')
end, false)

Hotbar Not Working

Problem: Hotbar items don’t activate when pressed.

Solutions:

  1. Check keybinding configuration
  2. Verify item usability settings
  3. Check for conflicting resources
-- Debug hotbar usage
RegisterKeyMapping('slot1', 'Use Hotbar Slot 1', 'keyboard', '1')
RegisterCommand('+slot1', function()
    local Player = QBCore.Functions.GetPlayerData()
    local item = Player.items[1]
    
    if item then
        print("Using item: " .. item.name)
        TriggerEvent('qb-inventory:client:useItem', item.name, item)
    end
end, false)

Performance Optimization

-- Optimize inventory updates
Config.UpdateInterval = 1000 -- Update every second instead of real-time
Config.MaxHistoryEntries = 50 -- Limit transaction history
 
-- Disable features if not needed
Config.Durability = false -- Disable durability system
Config.Crafting.enabled = false -- Disable crafting
Config.VehicleInventory = false -- Disable vehicle storage
  • qb-core - Core framework functions
  • qb-shops - Shopping system integration
  • qb-weapons - Weapon system integration
  • qb-houses - Housing storage system
  • qb-target - Interaction system

Support

For issues and feature requests: