Poradnik ox_inventory: wiodący ekwipunek dla FiveM w 2026 roku
Opanuj ox_inventory na swoim serwerze FiveM. Instaluj, konfiguruj przedmioty, podpinaj eksporty i integruj z frameworkami QBCore, ESX lub standalone.
Agency Scripts
Założyciel i główny deweloper w Agency Scripts
Czym jest ox_inventory?
ox_inventory to nowoczesny, wysoce wydajny system ekwipunku dla FiveM, który stał się standardowym wyborem dla poważnych serwerów roleplay. Stworzony przez zespół Overextended, zastępuje starsze rozwiązania ekwipunku systemem szybszym, bardziej elastycznym i łatwiejszym w rozbudowie. Oferuje elegancki UI oparty na React, wbudowane zarządzanie bronią, obsługę craftingu, sklepy, stashe oraz potężne API, które deweloperzy skryptów mogą wykorzystać do tworzenia niestandardowych interakcji z przedmiotami. Niezależnie od tego, czy budujesz nowy serwer, czy migrujesz z innego ekwipunku, dogłębne zrozumienie ox_inventory uczyni cię lepszym deweloperem FiveM.
Instalacja i konfiguracja
ox_inventory wymaga ox_lib jako zależność i działa zarówno z frameworkami ESX, jak i QBCore, a także w konfiguracjach standalone. Instalacja obejmuje pobranie zasobu, zaimportowanie schematu SQL do bazy danych i skonfigurowanie bridge frameworka. Plik konfiguracyjny kontroluje wszystko: od limitów wagi ekwipunku po liczniki psucia się przedmiotów.
-- Configuration snippet from ox_inventory
return {
playerslots = 50,
playerweight = 30000,
playerweaponslots = 5,
decay = true,
decayInterval = 60,
trunkslots = 50,
trunkweight = 60000,
gloveboxslots = 5,
gloveboxweight = 5000,
}
Rejestracja własnych przedmiotów
Przedmioty w ox_inventory są zdefiniowane w data/items.lua plik. Każdy przedmiot wymaga unikalnej nazwy, etykiety, wagi oraz opcjonalnie wielkości stosu, wskaźnika zużycia, opisu i procedur obsługi zdarzeń po stronie klienta lub serwera. Zrozumienie pełnego schematu definicji przedmiotów pozwala tworzyć przedmioty, które robią dokładnie to, czego potrzebują twoje skrypty.
-- 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',
}
},
}
Korzystanie z Server API ox_inventory
Exporty po stronie serwera to najczęściej używana część ox_inventory, pozwalająca dodawać przedmioty, usuwać przedmioty, sprawdzać zawartość ekwipunku i modyfikować metadane. Zawsze używaj API po stronie serwera do manipulacji przedmiotami, aby zapobiec exploitom ze strony cheaterów.
-- 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
Praca z metadanymi przedmiotów
Metadane przedmiotów to jedna z najpotężniejszych funkcji ox_inventory. Pozwala dołączać dowolne dane do pojedynczych instancji przedmiotów, umożliwiając unikalne numery seryjne broni, daty ważności żywności, imiona i nazwiska graczy na dowodach tożsamości oraz niestandardowe właściwości dowolnego przedmiotu.
-- 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)
Tworzenie własnych sklepów
ox_inventory zawiera wbudowany system sklepów, który możesz skonfigurować za pomocą niestandardowych katalogów przedmiotów, cen, ograniczeń prac i lokalizacji. Sklepy są definiowane w data/shops.lua i może być przypisany do pedów handlarzy, lokalizacji blipów lub wyzwalany programowo.
-- 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,
},
},
}
System stashy i niestandardowe kontenery
Stashe to trwałe kontenery magazynowe, do których gracze mają dostęp w określonych lokalizacjach. ox_inventory obsługuje stashe osobiste powiązane z identyfikatorem gracza, stashe współdzielone dostępne dla każdego oraz stashe z ograniczeniem do prac dla policyjnych magazynów dowodów i magazynów szpitalnych.
-- 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)
Dobre praktyki dotyczące integracji z ox_inventory
- Zawsze waliduj po stronie serwera. Nigdy nie ufaj weryfikacjom ekwipunku po stronie klienta. Używaj exportów serwerowych, takich jak
GetItemCountiRemoveItemdla całej krytycznej logiki gry. - Używaj metadanych z umiarem. Choć metadane dają duże możliwości, zapisywanie nadmiernej ilości danych przy każdym przedmiocie zwiększa rozmiar bazy danych i ruch sieciowy. Zapisuj tylko to, czego naprawdę potrzebujesz.
- Płynna obsługa pełnych ekwipunków. Zawsze sprawdzaj wartość zwracaną przez
AddItemi przekaż graczowi czytelną informację zwrotną, gdy jego ekwipunek jest pełny. - Używaj zużywania się przedmiotów dla większego realizmu. Właściwość degrade tworzy naturalne ujścia dla przedmiotów, pomagając utrzymać równowagę w gospodarce. Ustaw odpowiedni czas niszczenia dla towarów łatwo psujących się oraz narzędzi.
- Wykorzystaj wbudowany system craftingu. Zamiast tworzyć własną logikę craftingu, użyj stołów rzemieślniczych ox_inventory, które automatycznie obsługują sprawdzanie, usuwanie i tworzenie.
- Dbaj o spójność grafik przedmiotów. Umieść wszystkie obrazy przedmiotów w
web/images/z pasującymi nazwami plików. Użyj plików PNG o wymiarach 100x100 z przezroczystym tłem, aby uzyskać najbardziej przejrzysty wygląd.