Qu'est-ce que ox_lib et pourquoi devriez-tu l'utiliser ?
ox_lib est une bibliothèque d'utilitaires open source pour FiveM qui est devenue la norme de facto pour le développement de scripts modernes. Il fournit une collection massive de composants d'interface utilisateur, de fonctions utilitaires et d'outils de performances prédéfinis qui éliminent le besoin de réinventer la roue pour chaque script que tu écrives. Avant que ox_lib n'existe, les développeurs devaient créer leurs propres systèmes de notification, boîtes de dialogue de saisie, barres de progression et menus contextuels à partir de zéro, ce qui entraînait souvent une interface utilisateur incohérente entre différents scripts sur le même serveur. ox_lib résout ce problème en fournissant un ensemble de composants unifiés et raffinés qui semblent professionnels et fonctionnent de manière fiable dès la sortie de la boîte. Il prend en charge à la fois Lua et JavaScript, fonctionne avec n'importe quel framework (QBCore, ESX ou autonome) et est activement maintenu par l'équipe Overextended. Si tu écrives des scripts FiveM en 2026 et n'utilisez pas ox_lib, tu passes un temps inutile à créer des éléments qui existent déjà.
Configuration de ox_lib dans ton ressource
Intégrer ox_lib à ton ressource ne nécessite que deux étapes : ajouter la dépendance à ton fxmanifest.lua et appeler la bibliothèque dans tes scripts. Le @ox_lib/init.lua L'importation tu donne accès à tous les utilitaires partagés, tandis que le système de modules tu permet de charger de manière sélective uniquement les fonctionnalités dont tu as besoin. Cela permet de conserver une ressource légère car les modules inutilisés ne sont jamais chargés. Assurez-tu que ox_lib est démarré avant ton ressource dans ton server.cfg en plaçant ensure ox_lib au-dessus de tes ressources personnalisées. Voici la configuration minimale pour une nouvelle ressource utilisant ox_lib :
-- fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
name 'my-awesome-script'
version '1.0.0'
-- Required: import ox_lib
shared_scripts {
'@ox_lib/init.lua',
'config.lua',
}
client_scripts {
'client/*.lua',
}
server_scripts {
'server/*.lua',
}
-- Declare ox_lib as a dependency
dependencies {
'ox_lib',
}
-- Enable ox_lib locale system (optional)
lua54 'yes'
Notifications : alertes claires et cohérentes
Les notifications ox_lib remplacent les messages de discussion par défaut et les fenêtres contextuelles NUI personnalisées que la plupart des scripts utilisent. Ils apparaissent sous forme de messages toasts élégants avec des icônes, des couleurs et un renvoi automatique. Tu peux définir la position, la durée, le type (succès, erreur, avertissement, info) et même ajouter une description sous le titre. Le système de notification est uniquement côté client et incroyablement léger, n’ajoutant pratiquement aucune surcharge à ton script. Les notifications sont la fonctionnalité ox_lib la plus couramment utilisée et devraient constituer ton moyen par défaut de communiquer des commentaires aux joueurs dans tout script que tu crées.
-- client.lua: Notification examples
-- Simple notification
lib.notify({
title = 'Vehicle Stored',
description = 'Your vehicle has been stored in the garage.',
type = 'success', -- 'success' | 'error' | 'warning' | 'info'
duration = 5000, -- milliseconds
position = 'top-right', -- 'top' | 'top-right' | 'top-left' | 'bottom' | 'bottom-right' | 'bottom-left'
})
-- Error notification with icon
lib.notify({
title = 'Access Denied',
description = 'You do not have the required key.',
type = 'error',
icon = 'lock',
iconColor = '#ff4444',
})
-- Notification from server side
-- server.lua
RegisterNetEvent('garage:store', function()
local src = source
TriggerClientEvent('ox_lib:notify', src, {
title = 'Garage',
description = 'Vehicle stored successfully.',
type = 'success',
})
end)
Menus contextuels : listes d'options interactives
Les menus contextuels sont des listes déroulantes d'options sur lesquelles les joueurs peuvent cliquer pour déclencher des actions. Ils sont parfaits pour les menus de tâches, les interfaces de magasin, les options de véhicules et tout scénario dans lequel un joueur doit choisir parmi plusieurs actions. Chaque élément de menu peut avoir une icône, une description, des métadonnées affichées sur le côté droit et des sous-menus imbriqués pour organiser des arborescences d'options complexes. Le menu reste ouvert jusqu'à ce que le joueur le ferme explicitement ou sélectionne une option hors sous-menu, ce qui le rend idéal pour parcourir les catégories d'éléments. Les menus contextuels peuvent également être générés dynamiquement sur la base des données du serveur, afin que tu puissies créer des menus de boutique qui reflètent l'inventaire en temps réel à partir de ton base de données.
-- client.lua: Context menu examples
-- Simple shop menu
lib.registerContext({
id = 'weapons_shop',
title = 'Ammu-Nation',
options = {
{
title = 'Pistol',
description = 'Standard 9mm handgun',
icon = 'gun',
metadata = {
{label = 'Price', value = '$2,500'},
{label = 'Ammo', value = '12 rounds'},
},
onSelect = function()
TriggerServerEvent('shop:buy', 'weapon_pistol')
end,
},
{
title = 'Body Armor',
description = 'Standard kevlar vest',
icon = 'shield',
metadata = {
{label = 'Price', value = '$5,000'},
{label = 'Protection', value = '50%'},
},
onSelect = function()
TriggerServerEvent('shop:buy', 'armor')
end,
},
{
title = 'Attachments',
description = 'Browse weapon modifications',
icon = 'wrench',
arrow = true, -- Shows arrow indicating submenu
menu = 'attachments_submenu',
},
},
})
lib.showContext('weapons_shop')
Barres de progression et cercles de progression
Les barres de progression donnent un retour visuel lors d'actions chronométrées comme le crochetage, l'artisanat, la réparation de véhicules ou la cuisson de nourriture. ox_lib fournit à la fois une barre linéaire et un indicateur circulaire. Pendant l'animation de progression, tu peux désactiver les commandes du joueur telles que le mouvement, le combat et l'entrée de la voiture pour empêcher les exploits. Tu peux également attacher une animation et un accessoire au joueur afin qu'il effectue visiblement l'action pendant que la barre se remplit. La fonction renvoie true si le joueur a annulé l'action (en se déplaçant par exemple) et false s'il s'est terminé avec succès. Vérifiez toujours cette valeur de retour pour éviter d'accorder des objets ou de terminer des actions interrompues par le joueur.
-- client.lua: Progress bar examples
-- Linear progress bar with animation
local cancelled = lib.progressBar({
duration = 8000,
label = 'Lockpicking door...',
useWhileDead = false,
canCancel = true,
disable = {
car = true,
move = true,
combat = true,
},
anim = {
dict = 'anim@amb@clubhouse@tutorial@bkr_tut_ig3@',
clip = 'machinic_loop_mechandler',
},
prop = {
model = 'prop_lockpick_01',
bone = 57005,
pos = vec3(0.14, 0.0, -0.01),
rot = vec3(0.0, 0.0, 0.0),
},
})
if cancelled then
lib.notify({ title = 'Cancelled', type = 'error' })
else
lib.notify({ title = 'Door Unlocked', type = 'success' })
TriggerServerEvent('lockpick:success', doorId)
end
-- Circular progress (useful for quick actions)
if lib.progressCircle({
duration = 2000,
label = 'Searching...',
position = 'bottom',
useWhileDead = false,
canCancel = true,
disable = { move = true },
}) then
lib.notify({ title = 'Search cancelled', type = 'error' })
else
TriggerServerEvent('search:complete')
end
Boîtes de dialogue de saisie : collecte des données du joueur
Les boîtes de dialogue de saisie tu permettent de collecter du texte saisi, des chiffres, des sélections déroulantes, des cases à cocher, des sélecteurs de couleurs, des dates et des valeurs de curseur auprès des joueurs via une interface modale propre. Ceci est essentiel pour les scripts qui nécessitent la contribution du joueur, comme la définition du prix d'une maison, la saisie d'une plaque d'immatriculation, le nom d'un gang ou la configuration des paramètres d'une tâche. Chaque champ de saisie comporte une étiquette, une description facultative, un indicateur requis et des options spécifiques au type telles que des valeurs min/max pour les nombres ou des options prédéfinies pour les listes déroulantes. La fonction renvoie nil si le joueur annule la boîte de dialogue et un tableau de valeurs dans l'ordre des champs s'il se soumet. Validez toujours les données renvoyées sur le client et le serveur pour éviter les exploits.
-- client.lua: Input dialog examples
-- Vehicle listing form
local input = lib.inputDialog('List Vehicle for Sale', {
{ type = 'input', label = 'Title', description = 'Name for the listing', required = true, max = 50 },
{ type = 'number', label = 'Price ($)', description = 'Asking price', required = true, min = 1000, max = 10000000 },
{ type = 'select', label = 'Condition', options = {
{ value = 'new', label = 'Brand New' },
{ value = 'used', label = 'Used - Good' },
{ value = 'damaged', label = 'Damaged' },
}},
{ type = 'textarea', label = 'Description', description = 'Describe your vehicle', max = 500 },
{ type = 'checkbox', label = 'I agree to the marketplace terms' },
})
if not input then return end -- Player cancelled
local title, price, condition, description, agreedTerms = table.unpack(input)
if not agreedTerms then
lib.notify({ title = 'You must agree to the terms', type = 'error' })
return
end
TriggerServerEvent('marketplace:list', {
title = title,
price = price,
condition = condition,
description = description,
})
Zones : détection de zone efficace
Les zones ox_lib remplacent l'ancienne méthode inefficace de vérification de la position du joueur à chaque image par GetEntityCoords et mathématiques à distance. Le système de zone utilise un algorithme de détection spatiale optimisé qui vérifie uniquement les coordonnées à des intervalles configurables et déclenche des rappels d'entrée/sortie lorsque les joueurs franchissent les limites de la zone. Tu peux définir des zones sous forme de sphères, de boîtes ou de polygones, ce qui les rend suffisamment flexibles pour tout, des petits points d'interaction aux grandes limites de quartier. Les zones prennent en charge la rotation, le dessin de débogage pour le développement et les données arbitraires transmises aux rappels. Pour tout script devant détecter lorsqu'un joueur se trouve dans une zone spécifique, les zones ox_lib sont la solution la plus performante disponible.
-- client.lua: Zone examples
-- Sphere zone for a shop entrance
local shopZone = lib.zones.sphere({
coords = vec3(25.7, -1347.3, 29.5),
radius = 3.0,
debug = true, -- Set false in production
onEnter = function(self)
lib.notify({ title = 'Press [E] to open shop', type = 'info' })
lib.showTextUI('[E] Open Shop', { position = 'right-center' })
end,
onExit = function(self)
lib.hideTextUI()
end,
})
-- Box zone with rotation for a parking spot
local parkingZone = lib.zones.box({
coords = vec3(215.3, -810.0, 30.7),
size = vec3(6.0, 3.0, 2.0),
rotation = 70.0,
debug = true,
onEnter = function(self)
lib.showTextUI('[E] Store Vehicle')
end,
onExit = function(self)
lib.hideTextUI()
end,
})
-- Clean up zones when resource stops
AddEventHandler('onResourceStop', function(resource)
if resource == GetCurrentResourceName() then
shopZone:remove()
parkingZone:remove()
end
end)
Cache : accès intelligent aux données
Le lib.cache Le module fournit un accès instantané aux données fréquemment nécessaires du joueur sans effectuer d'appels natifs à chaque image. Des valeurs comme cache.ped, cache.vehicle, cache.seat, cache.weapon, et cache.playerId sont automatiquement tenus à jour par ox_lib via des écouteurs d'événements plutôt que par des sondages. Cela signifie que tu peux lire en toute sécurité cache.vehicle n'importe où dans ton code sans tu soucier des performances. Le cache déclenche également des événements lorsque les valeurs changent, tu peux donc enregistrer des gestionnaires pour ox_lib:cache:vehicle pour réagir lorsqu'un joueur entre ou sort d'un véhicule. Combiné avec les zones et le reste du ox_lib, le système de cache tu permet d'écrire du code propre et piloté par des événements au lieu de boucles d'interrogation basées sur des trames qui gaspillent des cycles CPU en vérifiant des conditions qui changent rarement.
-- client.lua: Cache examples
-- Access cached values (no native calls needed)
local myPed = cache.ped
local myVehicle = cache.vehicle -- nil if not in a vehicle
local mySeat = cache.seat -- -1 = driver, 0 = front passenger, etc.
local myWeapon = cache.weapon
-- React to vehicle changes
lib.onCache('vehicle', function(vehicle)
if vehicle then
-- Player entered a vehicle
local plate = GetVehicleNumberPlateText(vehicle)
lib.notify({
title = 'Vehicle',
description = 'Plate: ' .. plate,
type = 'info',
})
else
-- Player exited a vehicle
lib.notify({ title = 'On foot', type = 'info' })
end
end)
-- React to weapon changes
lib.onCache('weapon', function(weapon)
if weapon then
print('Player equipped weapon:', weapon)
end
end)
