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:
ensure oxmysql
ensure ox_lib
ensure qbx_core
ensure ox_inventory
ensure ox_target
ensure my_scriptRemova 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
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:
-- 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)
endAmbas 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 |
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' })
endAddItem 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:
-- QBCore
QBCore.Functions.Notify('Done', 'success', 5000)
-- ox_lib (client)
lib.notify({ title = 'Job', description = 'Done', type = 'success', duration = 5000 })-- 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')
endMenus 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:
-- 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 exportpara 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 usaQBCore.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-coresobrando iniciado ao lado deqbx_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 →