Converter um script QBCore para QBox: qbx_core, ox_inventory, ox_target

Como portar um script QBCore para QBox: a camada de compatibilidade qbx_core, GetPlayer, itens ox_inventory, ox_lib notify e progress, ox_target, e o que geralmente quebra.

Você tem um script escrito para QBCore e um servidor rodando QBox. Às vezes ele inicia e funciona, às vezes o console se enche com erros sobre um qb-inventory, qb-target ou qb-menu faltando. Aqui está a ordem para portá-lo, e os lugares onde geralmente quebra.

Se você ainda está escolhendo um core, o mesmo trabalho da outra direção está em convert an ESX script to QBCore.

O que QBox muda e o que mantém

QBox é construído em qbx_core mais os recursos Overextended: ox_lib, oxmysql, ox_inventory e ox_target. Ele mantém uma camada de compatibilidade, então exports['qb-core']:GetCoreObject() ainda responde e PlayerData tem a mesma forma (citizenid, job, charinfo, metadata, money). É por isso que muitos scripts rodam intocados.

O que não mantém são os velhos recursos de utilidade QB. Onde QBCore usava qb-inventory, qb-target, qb-menu, qb-input e qb-progressbar, QBox espera ox_inventory, ox_target e ox_lib. Essas são as partes que você porta.

O primeiro passo é garantir que o core seja iniciado corretamente:

cfg
ensure oxmysql
ensure ox_lib
ensure qbx_core
ensure ox_inventory
ensure ox_target
ensure my_script

Remova qualquer pasta qb-core restante, já que dois cores conflitam. Veja QBCore is nil: GetCoreObject se o objeto está faltando.

Passo 1: dependências no manifesto

lua
fx_version 'cerulean'
game 'gta5'
lua54 'yes'

shared_script '@ox_lib/init.lua'

dependencies { 'qbx_core', 'ox_lib', 'ox_inventory', 'ox_target' }

@ox_lib/init.lua é o que lhe dá o global lib. Se não for encontrado, veja ox_lib init.lua not found.

Passo 2: obtendo o jogador

Ambas funcionam em QBox. A primeira é o estilo de compatibilidade, a segunda é o jeito QBox:

lua
-- QBCore style (still works through the compatibility layer)
local QBCore = exports['qb-core']:GetCoreObject()
local Player = QBCore.Functions.GetPlayer(source)

-- QBox style
local player = exports.qbx_core:GetPlayer(source)
if player then
    print(player.PlayerData.citizenid, player.PlayerData.job.name)
end

Ambas retornam nil para um jogador que não foi carregado, então mantenha a verificação nil. Para encontrar um jogador carregado por citizen id, QBox também tem GetPlayerByCitizenId. Quando você porta, você pode deixar as chamadas do QBCore no lugar e substituí-las uma por uma depois.

Passo 3: inventário

É aqui que a maioria dos scripts quebra. qb-inventory e ox_inventory não compartilham definições de itens ou nomes de funções.

Tarefa QBCore QBox com ox_inventory
Adicionar um item Player.Functions.AddItem('water', 1) exports.ox_inventory:AddItem(source, 'water', 1)
Remover um item Player.Functions.RemoveItem('water', 1) exports.ox_inventory:RemoveItem(source, 'water', 1)
Contagem Player.Functions.GetItemByName('water').amount exports.ox_inventory:GetItemCount(source, 'water')
Metadados tabela info tabela metadata
lua
local src = source
local ok = exports.ox_inventory:AddItem(src, 'water', 2, { quality = 100 })
if not ok then
    lib.notify(src, { description = 'Your inventory is full', type = 'error' })
end

AddItem retorna um valor falsy quando o item não existe ou não pode ser carregado, então verifique. Definições de item se movem também. QBCore as mantém em qb-core/shared/items.lua, ox_inventory em ox_inventory/data/items.lua. Adicione todo item que o script usa lá, no formato de ox_inventory. Como fazer isso está em add items to ox_inventory, e o formato QBCore de onde você está vindo está em add items to qb-inventory.

Itens usáveis também são registrados diferentemente: QBCore.Functions.CreateUseableItem se torna uma export definida na definição do item em ox_inventory, que aponta para uma função em seu script. As chamadas do QBCore ainda podem funcionar através da camada de compatibilidade, então teste um item antes de reescrevê-lo.

Passo 4: notificações, progress e menus com ox_lib

ox_lib substitui os recursos de utilidade QB separados. As chamadas são próximas ao que você conhece:

lua
-- QBCore
QBCore.Functions.Notify('Done', 'success', 5000)

-- ox_lib (client)
lib.notify({ title = 'Job', description = 'Done', type = 'success', duration = 5000 })
lua
-- QBCore: QBCore.Functions.Progressbar(...) with a callback
-- ox_lib: returns true when completed, false when cancelled
if lib.progressBar({
    duration = 5000,
    label = 'Repairing',
    useWhileDead = false,
    canCancel = true,
    disable = { car = true, move = true },
    anim = { dict = 'mini@repair', clip = 'fixing_a_ped' },
}) then
    print('finished')
else
    print('cancelled')
end

Menus se movem de qb-menu para lib.registerContext e lib.showContext, e formulários de input de qb-input para lib.inputDialog. Exemplos completos estão em notifications and progress bars on ESX, QBCore and ox_lib e ox_lib context menus.

Passo 5: ox_target em vez de qb-target

qb-target toma um nome, coordenadas e uma tabela de opções em seu próprio layout. ox_target toma uma tabela:

lua
-- qb-target
exports['qb-target']:AddBoxZone('my_zone', vector3(215.0, -810.0, 30.7), 1.5, 1.5, {
    name = 'my_zone', heading = 0, minZ = 29.7, maxZ = 32.7,
}, {
    options = { { event = 'my_script:client:open', icon = 'fas fa-box', label = 'Open', job = 'police' } },
    distance = 2.0,
})

-- ox_target
exports.ox_target:addBoxZone({
    coords = vector3(215.0, -810.0, 30.7),
    size = vector3(1.5, 1.5, 3.0),
    rotation = 0,
    options = {
        { name = 'my_zone_open', icon = 'fas fa-box', label = 'Open', groups = 'police',
          onSelect = function() TriggerEvent('my_script:client:open') end },
    },
})

Repare que event se torna onSelect (ou event ainda funciona para um evento de cliente), e job se torna groups. Os detalhes estão em qb-target vs ox_target e ox_target zones.

O que geralmente quebra

  • Erros de item faltando. O item existe no arquivo compartilhado do qb-core mas não em ox_inventory. Adicione-o.
  • No such export para qb-inventory, qb-target ou qb-menu. O script os chama diretamente: porte essas chamadas, ou nunca rodará.
  • Callbacks. lib.callback é o estilo QBox. Se um script ainda usa QBCore.Functions.CreateCallback, teste-o e mova para ox_lib se falhar: veja server callbacks.
  • Jobs e gangs com grades. QBox tem seus próprios dados de job e grupo. Teste toda verificação de job, especialmente on-duty e comparações de grade.
  • Cores mistos. Um recurso qb-core sobrando iniciado ao lado de qbx_core.
  • Ordem de início. Seu script acima de ox_lib, ox_inventory ou qbx_core em server.cfg.

Checklist

Sintoma Solução
GetCoreObject é nil Inicie qbx_core primeiro e remova qualquer pasta qb-core
No such export para qb-inventory Use exports.ox_inventory:AddItem(source, item, count)
Item não encontrado Adicione a ox_inventory/data/items.lua
Chamadas de qb-target falham Porte para exports.ox_target:addBoxZone ou addLocalEntity
lib é nil Adicione shared_script '@ox_lib/init.lua'
Verificação de job sempre false Teste PlayerData.job.name e grade em QBox

Respostas rápidas

Scripts do QBCore funcionam em QBox sem mudanças?

Muitos funcionam, porque qbx_core mantém uma camada de compatibilidade para qb-core. Scripts que dependem de qb-inventory, qb-target ou qb-menu geralmente precisam de trabalho, já que QBox usa ox_inventory, ox_target e ox_lib em vez disso.

Como obtenho o jogador em QBox?

No servidor, exports.qbx_core:GetPlayer(source) retorna o jogador, com a mesma tabela PlayerData que você conhece de QBCore.

Preciso reescrever tudo para mudar para QBox?

Não. Inicie o script em QBox, leia os erros, e substitua os pedaços que falham: inventário, target, menus e notificações. O resto, como PlayerData, jobs e metadados, mantém sua forma.

Scripts sem esse problema

Item Creator V2Crie itens usáveis com animações, props, efeitos e muito mais — sem escrever código.Ver script →Shop CreatorMonte uma loja em menos de um minuto — donos, funcionários, cofres e assaltos inclusos.Ver script →Quest CreatorUm editor visual de missões e diálogos com NPCs, montado nó por nó dentro do jogo.Ver script →

Continue lendo