Stick's Resources

Patching ox_inventory

Replace ox_inventory's static data file loader with the ItemsDB integration.

This patch is not officially supported by overextended. Do not report issues caused by this patch to them. If you encounter a problem, please open an issue on our GitHub here.

Before migrating, patch path_to_ox_inventory/modules/items/shared.lua so ox_inventory loads items from ItemsDB instead of its data files.

Replace lines 76-116 (the two lib.load loops) with the block below. Leave everything else untouched.

The block below must match your file exactly before you replace it. If your version of ox_inventory differs, the line numbers or content may not align. Double-check before making any changes.

Lines to Remove (76-116)

for type, data in pairs(lib.load('data.weapons') or {}) do
	for k, v in pairs(data) do
		v.name = k
		v.close = type == 'Ammo' and true or false
        v.weight = v.weight or 0

		if type == 'Weapons' then
			---@cast v OxWeapon
			v.model = v.model or k
			v.hash = joaat(v.model)
			v.stack = v.throwable and true or false
			v.durability = v.durability or 0.05
			v.weapon = true
		else
			v.stack = true
		end

		v[type == 'Ammo' and 'ammo' or type == 'Components' and 'component' or type == 'Tints' and 'tint' or 'weapon'] = true

		if isServer then v.client = nil else
			v.count = 0
			v.server = nil
			local clientData = v.client

			if clientData?.image then
                clientData.image = setImagePath(clientData.image)
			end
		end

		ItemList[k] = v
	end
end

for k, v in pairs(lib.load('data.items') or {}) do
	v.name = k
	local success, response = pcall(newItem, v)

    if not success then
        warn(('An error occurred while creating item "%s" callback!\n^1SCRIPT ERROR: %s^0'):format(k, response))
    end
end

Replacement Block

-- [ItemsDB patched]
if isServer then
	local function processWeapon(name, v, category)
		v.name     = name
		v.close    = category == 'Ammo'
		v.weight   = v.weight or 0
		if category == 'Weapons' then
			v.model      = v.model or name
			v.hash       = joaat(v.model)
			v.stack      = v.throwable and true or false
			v.durability = v.durability or 0.05
			v.weapon     = true
		else
			v.stack = true
		end
		v[category == 'Ammo' and 'ammo' or category == 'Components' and 'component' or category == 'Tints' and 'tint' or 'weapon'] = true
		v.client       = nil
		ItemList[name] = v
	end

	local function loadFromFiles()
		for category, data in pairs(lib.load('data.weapons') or {}) do
			for k, v in pairs(data) do processWeapon(k, v, category) end
		end
		for k, v in pairs(lib.load('data.items') or {}) do
			v.name = k
			local ok, err = pcall(newItem, v)
			if not ok then
				warn(('An error occurred while creating item "%s" callback!\n^1SCRIPT ERROR: %s^0'):format(k, err))
			end
		end
	end

	local function loadFromItemsDB(allData)
		for k in pairs(ItemList) do ItemList[k] = nil end
		local count = 0
		for name, v in pairs(allData) do
			if v.category then
				processWeapon(name, v, v.category)
			else
				v.name = name
				local ok, err = pcall(newItem, v)
				if not ok then
					warn(('An error occurred while creating item "%s" callback!\n^1SCRIPT ERROR: %s^0'):format(name, err))
				end
			end
			count += 1
		end
		ItemList.cash = ItemList.money
		return count
	end

	local function broadcastClientSync()
		local clientView = exports.ItemsDB:getClientItems()
		if clientView and next(clientView) then
			TriggerClientEvent('ItemsDB:syncItems', -1, clientView)
		end
	end

	AddEventHandler('ItemsDB:serverItemUpdated', function(item)
		if not item or not item.name then return end
		if item.category then
			processWeapon(item.name, item, item.category)
		else
			local ok, err = pcall(newItem, item)
			if not ok then
				warn(('Error updating runtime item "%s": %s'):format(item.name, err))
			end
		end
		if item.name == 'money' then ItemList.cash = ItemList.money end
	end)

	AddEventHandler('ItemsDB:serverItemDeleted', function(name)
		if not name then return end
		ItemList[name] = nil
		if name == 'money' then ItemList.cash = nil end
	end)

	if GetResourceState('ItemsDB') == 'started' and exports.ItemsDB:isReady() then
		local allData = exports.ItemsDB:getItems()
		if allData and next(allData) then
			print('[ox_inventory] Loaded ' .. loadFromItemsDB(allData) .. ' items from ItemsDB')
			broadcastClientSync()
		else
			warn('[ox_inventory] ItemsDB returned no items - run `ItemsDB:migrate` then restart')
			loadFromFiles()
		end
	else
		loadFromFiles()

		CreateThread(function()
			local elapsed = 0
			while not (GetResourceState('ItemsDB') == 'started' and exports.ItemsDB:isReady()) do
				Wait(500)
				elapsed += 500
				if elapsed >= 15000 then
					warn('[ox_inventory] ItemsDB not ready after 15s - keeping data file items')
					return
				end
			end

			local allData = exports.ItemsDB:getItems()
			if not allData or not next(allData) then
				warn('[ox_inventory] ItemsDB returned no items - run `ItemsDB:migrate` then restart')
				return
			end

			print('[ox_inventory] Swapped to ItemsDB: ' .. loadFromItemsDB(allData) .. ' items')
			broadcastClientSync()
		end)
	end
else
	local function processWeaponClient(name, v, category)
		v.name   = name
		v.close  = category == 'Ammo'
		v.weight = v.weight or 0
		if category == 'Weapons' then
			v.model      = v.model or name
			v.hash       = joaat(v.model)
			v.stack      = v.throwable and true or false
			v.durability = v.durability or 0.05
			v.weapon     = true
		else
			v.stack = true
		end
		v[category == 'Ammo' and 'ammo' or category == 'Components' and 'component' or category == 'Tints' and 'tint' or 'weapon'] = true
		v.count  = 0
		v.server = nil
		local clientData = v.client
		if clientData and clientData.image then
			clientData.image = setImagePath(clientData.image)
		end
		ItemList[name] = v
	end

	local function applySync(data)
		local count = 0
		for name, v in pairs(data) do
			v.name = name
			if v.category then
				processWeaponClient(name, v, v.category)
			else
				local ok, err = pcall(newItem, v)
				if not ok then
					warn(('An error occurred while creating item "%s" callback!\n^1SCRIPT ERROR: %s^0'):format(name, err))
				end
			end
			count += 1
		end
		ItemList.cash = ItemList.money
		print(('[ox_inventory] Received %d items from ItemsDB'):format(count))
	end

	for category, data in pairs(lib.load('data.weapons') or {}) do
		for k, v in pairs(data) do processWeaponClient(k, v, category) end
	end
	for k, v in pairs(lib.load('data.items') or {}) do
		v.name = k
		local ok, err = pcall(newItem, v)
		if not ok then
			warn(('An error occurred while creating item "%s" callback!\n^1SCRIPT ERROR: %s^0'):format(k, err))
		end
	end

	RegisterNetEvent('ItemsDB:syncItems')
	AddEventHandler('ItemsDB:syncItems', applySync)

	RegisterNetEvent('ItemsDB:removeClientItems')
	AddEventHandler('ItemsDB:removeClientItems', function(names)
		if not names then return end
		for _, name in ipairs(names) do
			ItemList[name] = nil
			if name == 'money' then ItemList.cash = nil end
		end
	end)

	if GetResourceState('ItemsDB') == 'started' then
		TriggerServerEvent('ItemsDB:requestClientItems')
	end
end

Apply the Patch

After saving the file, you can restart ox_inventory with:

restart ox_inventory

The [ox_inventory] Loaded N items count in the console should match what it was before.

Do not use restart ox_inventory on a live production server. It will drop all active inventories mid-session. We recommend scheduling a full server restart instead.

On this page