Назад к блогу
Tutorial5 мин чтения

ox_inventory Руководство: Лучший инвентарь FiveM в 2026 году

Освойте ox_inventory на вашем сервере FiveM. Установка, настройка предметов, подключение экспортов и интеграция с QBCore, ESX или standalone фреймворками.

Agency Scripts

Основатель и ведущий разработчик Agency Scripts

Что такое ox_inventory?

ox_inventory , современная, высокопроизводительная система инвентаря для FiveM, ставшая стандартным выбором для серьезных ролевых серверов. Созданная командой Overextended, она заменяет старые решения инвентаря системой, которая быстрее, гибче и проще в расширении. В ней есть стильный UI на базе React, встроенное управление оружием, поддержка крафта, магазины, хранилища и мощный API, который разработчики скриптов могут использовать для создания пользовательских взаимодействий с предметами. Независимо от того, создаете ли вы новый сервер или мигрируете с другого инвентаря, глубокое понимание ox_inventory сделает вас лучшим разработчиком FiveM.

Установка и конфигурация

ox_inventory требует ox_lib как зависимость и работают как с ESX, так и с QBCore, а также в standalone-режиме. Установка включает скачивание ресурса, импорт SQL-схемы в базу данных и настройку моста для фреймворка. Файл конфигурации управляет всем: от лимитов веса инвентаря до таймеров порчи предметов.

-- Configuration snippet from ox_inventory
return {
    playerslots = 50,
    playerweight = 30000,
    playerweaponslots = 5,

    decay = true,
    decayInterval = 60,

    trunkslots = 50,
    trunkweight = 60000,
    gloveboxslots = 5,
    gloveboxweight = 5000,
}

Регистрация пользовательских предметов

Предметы в ox_inventory определяются в data/items.lua файл. Каждый предмет должен иметь уникальное имя, метку, вес и опционально размер стека, скорость разложения, описание и обработчики событий на клиенте или сервере. Понимание полной схемы определения предметов позволяет создавать предметы, которые делают именно то, что нужно вашим скриптам.

-- data/items.lua
return {
    ['water_bottle'] = {
        label = 'Water Bottle',
        weight = 500,
        stack = true,
        close = true,
        description = 'A refreshing bottle of water',
        client = {
            image = 'water_bottle.png',
        }
    },

    ['lockpick'] = {
        label = 'Lockpick',
        weight = 200,
        stack = true,
        close = true,
        degrade = 300,
        description = 'Used to pick locks. Breaks after use.',
    },

    ['driver_license'] = {
        label = 'Driver License',
        weight = 0,
        stack = false,
        consume = 0,
        description = 'Issued by the DMV',
        client = {
            image = 'driver_license.png',
        }
    },
}

Использование ox_inventory Server API

Серверные экспорты , самая часто используемая часть ox_inventory, позволяющая добавлять предметы, удалять, проверять содержимое и управлять метаданными. Всегда используйте серверный API для манипуляций с предметами, чтобы предотвратить эксплойты читеров.

-- Server-side: Adding items to a player
RegisterNetEvent('myresource:giveReward', function(itemName, count)
    local src = source
    local success = exports.ox_inventory:AddItem(src, itemName, count)

    if success then
        TriggerClientEvent('ox_lib:notify', src, {
            title = 'Item Received',
            description = count .. 'x ' .. itemName,
            type = 'success'
        })
    else
        TriggerClientEvent('ox_lib:notify', src, {
            title = 'Inventory Full',
            description = 'Could not add item to inventory',
            type = 'error'
        })
    end
end)

-- Server-side: Check if player has required items
local function HasRequiredItems(src, requirements)
    for _, req in ipairs(requirements) do
        local count = exports.ox_inventory:GetItemCount(src, req.name)
        if count < req.amount then
            return false, req.name, req.amount - count
        end
    end
    return true
end

-- Server-side: Remove multiple items in a transaction
local function ConsumeRecipeItems(src, recipe)
    for _, ingredient in ipairs(recipe.ingredients) do
        local removed = exports.ox_inventory:RemoveItem(
            src, ingredient.name, ingredient.amount
        )
        if not removed then
            print(('[ERROR] Failed to remove %s from player %d'):format(
                ingredient.name, src
            ))
            return false
        end
    end
    return true
end

Работа с метаданными предметов

Метаданные предметов , одна из самых мощных функций ox_inventory. Она позволяет прикреплять произвольные данные к отдельным экземплярам предметов, что даёт возможность уникальных серийных номеров на оружии, сроков годности на еде, имён игроков на удостоверениях и пользовательских свойств для любых предметов.

-- Server: Create a driver license with metadata
RegisterNetEvent('myresource:issueLicense', function(targetId, licenseType)
    local src = source

    local metadata = {
        type = licenseType,
        issued = os.date('%Y-%m-%d'),
        issuedBy = GetPlayerName(src),
        holder = GetPlayerName(targetId),
        expires = os.date('%Y-%m-%d', os.time() + 30 * 86400),
    }

    exports.ox_inventory:AddItem(targetId, 'driver_license', 1, metadata)
end)

-- Client: Reading metadata when using an item
exports('driver_license', function(data, slot)
    local item = exports.ox_inventory:GetSlot(slot)
    if not item or not item.metadata then return end

    local meta = item.metadata
    lib.notify({
        title = 'Driver License',
        description = ('Holder: %s\nType: %s\nExpires: %s'):format(
            meta.holder or 'Unknown',
            meta.type or 'Standard',
            meta.expires or 'N/A'
        ),
        type = 'inform'
    })
end)

Создание кастомных магазинов

ox_inventory включает встроенную систему магазинов, которую вы можете настроить с помощью пользовательских каталогов предметов, цен, ограничений по профессиям и локаций. Магазины определяются в data/shops.lua и может быть прикреплен к пешеходным продавцам, локациям на карте или вызван программно.

-- data/shops.lua
return {
    ['hardware_store'] = {
        name = 'Hardware Store',
        inventory = {
            { name = 'lockpick',    price = 150,  count = 10 },
            { name = 'screwdriver', price = 80,   count = 20 },
            { name = 'radio',       price = 250,  count = 5  },
            { name = 'repairkit',   price = 1000, count = 5  },
        },
        locations = {
            vec3(45.6, -1749.3, 29.6),
            vec3(2747.8, 3472.9, 55.7),
        },
        targets = {
            ped = 's_m_y_hardware_01',
            scenario = 'WORLD_HUMAN_STAND_IMPATIENT',
            distance = 2.5,
        },
    },
}

Система тайников и пользовательские контейнеры

Тайники , это постоянные контейнеры хранения, к которым игроки могут получить доступ в определённых местах. ox_inventory поддерживает личные тайники, привязанные к идентификатору игрока, общие тайники, доступные всем, и тайники с ограничением по работе, например, для комнат улик полиции и больничных хранилищ.

-- Server: Register a custom stash for a property
local function CreatePropertyStash(propertyId, owner)
    local stashId = ('property_%s'):format(propertyId)

    exports.ox_inventory:RegisterStash(
        stashId,
        ('Property #%s Storage'):format(propertyId),
        100,     -- slots
        200000,  -- max weight
        owner    -- owner identifier (or false for shared)
    )

    return stashId
end

-- Client: Open a stash when interacting with a storage point
RegisterNetEvent('myresource:openPropertyStorage', function(propertyId)
    local stashId = ('property_%s'):format(propertyId)
    exports.ox_inventory:openInventory('stash', stashId)
end)

Лучшие практики интеграции ox_inventory

  • Всегда валидируйте на стороне сервера. Никогда не доверяйте проверкам инвентаря на стороне клиента. Используйте серверные экспорты, такие как GetItemCount и RemoveItem для всей критической игровой логики.
  • Используйте метаданные умеренно. Хотя метаданные мощны, хранение избыточных данных для каждого предмета увеличивает размер базы данных и сетевой трафик. Храните только то, что действительно нужно.
  • Корректная обработка полных инвентарей. Всегда проверяйте возвращаемое значение AddItem и предоставьте игроку четкую обратную связь, когда его инвентарь заполнен.
  • Используйте деградацию предметов для реализма. Свойство degrade создаёт естественные поглотители предметов, поддерживающие баланс экономики. Устанавливайте соответствующие времена распада для скоропортящихся товаров и инструментов.
  • Используйте встроенную систему крафта. Вместо создания собственной логики крафта используйте верстаки ox_inventory, которые автоматически обрабатывают проверки, удаление и создание.
  • Сохраняйте изображения предметов единообразными. Размещайте все изображения предметов в web/images/ с совпадающими именами файлов. Используйте PNG-файлы 100x100 с прозрачным фоном для наилучшего вида.

Готовы начать?

Возьмите скрипты в нашем магазине или заходите в Discord за поддержкой, обновлениями и анонсами.