Tutorial 2026-04-23

O Guia Completo de ox_lib para Desenvolvimento em FiveM

TDYSKY

TDYSKY

Fundador & Lead Developer na Agency Scripts

O que é ox_lib e por que você deve usá-lo?

ox_lib é uma biblioteca utilitária de código aberto para FiveM que se tornou o padrão de fato para o desenvolvimento de scripts modernos. Ele fornece uma enorme coleção de componentes de UI pré-construídos, funções utilitárias e ferramentas de desempenho que eliminam a necessidade de reinventar a roda para cada script que você escreve. Antes da existência do ox_lib, os desenvolvedores tinham que construir seus próprios sistemas de notificação, caixas de diálogo de entrada, barras de progresso e menus de contexto do zero, muitas vezes resultando em UI inconsistente em diferentes scripts no mesmo servidor. ox_lib resolve isso fornecendo um conjunto unificado e sofisticado de componentes que parecem profissionais e funcionam de maneira confiável imediatamente. Ele suporta Lua e JavaScript, funciona com qualquer estrutura (QBCore, ESX ou independente) e é mantido ativamente pela equipe Overextended. Se você estiver escrevendo scripts FiveM em 2026 e não estiver usando ox_lib, estará gastando tempo desnecessário construindo coisas que já existem.

Configurando ox_lib em seu recurso

Colocar ox_lib em seu recurso requer apenas duas etapas: adicionar a dependência ao seu fxmanifest.lua e chamar a biblioteca em seus scripts. A importação @ox_lib/init.lua dá acesso a todos os utilitários compartilhados, enquanto o sistema de módulos permite carregar seletivamente apenas os recursos necessários. Isso mantém seu recurso leve porque os módulos não utilizados nunca são carregados. Certifique-se de que ox_lib seja iniciado antes de seu recurso em seu server.cfg, colocando ensure ox_lib acima de seus recursos personalizados. Aqui está a configuração mínima para um novo recurso que usa 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'

Notificações: alertas limpos e consistentes

As notificações ox_lib substituem as feias mensagens de bate-papo padrão e os pop-ups NUI personalizados que a maioria dos scripts usa. Eles aparecem como mensagens elegantes de brinde com ícones, cores e dispensa automática. Você pode definir a posição, duração, tipo (sucesso, erro, aviso, informação) e até mesmo adicionar uma descrição abaixo do título. O sistema de notificação é apenas do lado do cliente e é incrivelmente leve, adicionando praticamente nenhuma sobrecarga ao seu script. Notificações são o recurso ox_lib mais comumente usado e devem ser sua forma padrão de comunicar feedback aos jogadores em qualquer script que você criar.

-- 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 de contexto: listas de opções interativas

Os menus de contexto são listas roláveis ​​de opções nas quais os jogadores podem clicar para acionar ações. Eles são perfeitos para menus de trabalho, interfaces de lojas, opções de veículos e qualquer cenário onde um jogador precise escolher entre múltiplas ações. Cada item de menu pode ter um ícone, uma descrição, metadados exibidos no lado direito e submenus aninhados para organizar árvores de opções complexas. O menu permanece aberto até que o jogador o feche explicitamente ou selecione uma opção que não seja do submenu, o que o torna ideal para navegar pelas categorias de itens. Os menus de contexto também podem ser gerados dinamicamente com base nos dados do servidor, para que você possa criar menus de loja que reflitam o inventário em tempo real do seu banco de dados.

-- 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')

Barras de Progresso e Círculos de Progresso

As barras de progresso fornecem feedback visual durante ações cronometradas, como arrombar fechaduras, fabricar, consertar veículos ou cozinhar alimentos. ox_lib fornece uma barra linear e um indicador circular. Durante a animação de progresso, você pode desativar os controles do jogador, como movimento, combate e entrada de carro, para evitar explorações. Você também pode anexar uma animação e um acessório ao jogador para que ele execute a ação visivelmente enquanto a barra é preenchida. A função retorna true se o jogador cancelou a ação (movendo-se, por exemplo) e false se ela foi concluída com sucesso. Sempre verifique esse valor de retorno para evitar conceder itens ou concluir ações que o jogador interrompeu.

-- 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

Diálogos de entrada: coletando dados do jogador

As caixas de diálogo de entrada permitem coletar texto digitado, números, seleções suspensas, caixas de seleção, seletores de cores, datas e valores de controle deslizante dos jogadores por meio de uma interface modal limpa. Isso é essencial para scripts que precisam da participação do jogador, como definir o preço de uma casa, inserir uma placa de carro, nomear uma gangue ou definir configurações de trabalho. Cada campo de entrada possui um rótulo, uma descrição opcional, um sinalizador obrigatório e opções específicas de tipo, como valores mínimo/máximo para números ou opções predefinidas para menus suspensos. A função retorna nil se o jogador cancelar o diálogo e uma matriz de valores na ordem dos campos se ele enviar. Sempre valide os dados retornados no cliente e no servidor para evitar explorações.

-- 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,
})

Zonas: Detecção Eficiente de Área

As zonas ox_lib substituem o método antigo e ineficiente de verificar a posição do jogador em cada quadro com GetEntityCoords e matemática de distância. O sistema de zona usa um algoritmo de detecção espacial otimizado que verifica apenas as coordenadas em intervalos configuráveis ​​e aciona retornos de chamada de entrada/saída quando os jogadores cruzam os limites da zona. Você pode definir zonas como esferas, caixas ou polígonos, tornando-as flexíveis o suficiente para tudo, desde pequenos pontos de interação até grandes limites de vizinhança. As zonas suportam rotação, desenho de depuração para desenvolvimento e dados arbitrários que são passados ​​para os retornos de chamada. Para qualquer script que precise detectar quando um jogador está em uma área específica, as zonas ox_lib são a solução de melhor desempenho disponível.

-- 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: acesso inteligente a dados

O módulo lib.cache fornece acesso instantâneo aos dados do jogador frequentemente necessários, sem fazer chamadas nativas a cada quadro. Valores como cache.ped, cache.vehicle, cache.seat, cache.weapon e cache.playerId são mantidos automaticamente atualizados por ox_lib por meio de ouvintes de eventos em vez de pesquisa. Isso significa que você pode ler cache.vehicle com segurança em qualquer lugar do seu código sem se preocupar com o desempenho. O cache também dispara eventos quando os valores mudam, então você pode registrar manipuladores para ox_lib:cache:vehicle para reagir quando um jogador entra ou sai de um veículo. Combinado com zonas e o restante do ox_lib, o sistema de cache permite escrever código limpo e orientado a eventos, em vez de loops de pesquisa baseados em quadros que desperdiçam ciclos de CPU verificando condições que raramente mudam.

-- 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)

Partilhar este artigo

Pronto para melhorar o teu servidor?

Explora os nossos scripts FiveM premium na loja Agency Scripts ou junta-te à nossa comunidade no Discord para suporte e atualizações.