Converter um script ESX para QBCore (e voltar): mapa de funções e bridge

Porte um script FiveM entre ESX e QBCore: uma tabela das chamadas comuns (jogador, dinheiro, job, itens, notificações, callbacks) e um arquivo bridge que suporta ambos.

Você tem um script escrito para ESX, e seu servidor executa QBCore, ou o inverso. A maioria do script é Lua simples e natives que não mudam. Apenas as chamadas do framework mudam, e há menos do que você espera. Este artigo fornece um mapa delas, e então mostra como isolá-las em um arquivo bridge.

O que fica e o que muda

Natives, NUI, seus próprios eventos, loops, targets e menus funcionam em qualquer framework. O que muda é uma lista curta:

  • como você obtém o objeto do framework
  • como você obtém um jogador
  • dinheiro, jobs e itens
  • notificações
  • itens usáveis e callbacks
  • as tabelas do banco de dados para jogadores

Pesquise o script por ESX. e xPlayer, e cada resultado é algo para converter.

Mapa de funções

Tarefa ESX Legacy QBCore
Obter o objeto ESX = exports['es_extended']:getSharedObject() local QBCore = exports['qb-core']:GetCoreObject()
Obter um jogador (servidor) ESX.GetPlayerFromId(src) QBCore.Functions.GetPlayer(src)
Identificador de jogador xPlayer.identifier Player.PlayerData.citizenid
Saldo de dinheiro xPlayer.getMoney() Player.PlayerData.money.cash
Adicionar dinheiro xPlayer.addMoney(n) Player.Functions.AddMoney('cash', n)
Remover dinheiro xPlayer.removeMoney(n) Player.Functions.RemoveMoney('cash', n)
Adicionar ao banco xPlayer.addAccountMoney('bank', n) Player.Functions.AddMoney('bank', n)
Remover do banco xPlayer.removeAccountMoney('bank', n) Player.Functions.RemoveMoney('bank', n)
Nome de job xPlayer.job.name Player.PlayerData.job.name
Grade de job xPlayer.job.grade Player.PlayerData.job.grade.level
Adicionar item xPlayer.addInventoryItem(name, n) Player.Functions.AddItem(name, n)
Remover item xPlayer.removeInventoryItem(name, n) Player.Functions.RemoveItem(name, n)
Contagem de item xPlayer.getInventoryItem(name).count Player.Functions.GetItemByName(name) (nil se nenhum, depois .amount)
Item usável ESX.RegisterUsableItem(name, function(src) end) QBCore.Functions.CreateUseableItem(name, function(src, item) end)
Notificar (cliente) ESX.ShowNotification(msg) QBCore.Functions.Notify(msg, 'success')
Notificar (servidor) xPlayer.showNotification(msg) TriggerClientEvent('QBCore:Notify', src, msg, 'success')
Dados do jogador (cliente) ESX.GetPlayerData() QBCore.Functions.GetPlayerData()
Evento de jogador carregado esx:playerLoaded QBCore:Client:OnPlayerLoaded
Evento de job mudado esx:setJob QBCore:Client:OnJobUpdate
Server callback ESX.RegisterServerCallback QBCore.Functions.CreateCallback

Dois detalhes enganam as pessoas. Tipos de dinheiro: ESX tem money para dinheiro e bank, QBCore usa 'cash' e 'bank' como o primeiro argumento. E a grade: ESX dá um número simples, QBCore uma tabela, então job.grade.level.

Callbacks, que todo segundo script usa, são comparados em detalhes em server callbacks on ESX, QBCore and ox_lib.

O banco de dados

As tabelas de jogador diferem, então qualquer SELECT ou UPDATE nelas precisa de uma mudança:

ESX QBCore
Jogadores users players
Chave de jogador identifier (uma string license:) citizenid
Veículos owned_vehicles player_vehicles

Um script que armazena seus próprios dados, com suas próprias tabelas, geralmente continua funcionando, desde que ele chave as linhas em um valor que você pode obter de qualquer framework. Usar o identificador de license para isso funciona em ambos.

QBox

QBox é mais próximo de QBCore do que de ESX. Seu core é qbx_core, ele mantém uma camada de compatibilidade para exports['qb-core']:GetCoreObject(), e seu inventário é ox_inventory. Um script convertido para QBCore geralmente roda em QBox com poucas mudanças, além de chamadas de inventário.

A abordagem de arquivo bridge

Se o script deve rodar em ambos, não o polua com if ESX then ... else ... end. Coloque toda chamada do framework em um arquivo, e tenha o resto do script chamar esse arquivo.

lua
-- bridge.lua (server)
Bridge = {}

local framework
if GetResourceState('es_extended') == 'started' then
    framework = 'esx'
    ESX = exports['es_extended']:getSharedObject()
elseif GetResourceState('qb-core') == 'started' then
    framework = 'qb'
    QBCore = exports['qb-core']:GetCoreObject()
end

function Bridge.GetPlayer(src)
    if framework == 'esx' then return ESX.GetPlayerFromId(src) end
    return QBCore.Functions.GetPlayer(src)
end

function Bridge.AddCash(src, amount)
    local player = Bridge.GetPlayer(src)
    if not player then return false end

    if framework == 'esx' then
        player.addMoney(amount)
    else
        player.Functions.AddMoney('cash', amount)
    end
    return true
end

function Bridge.GetJob(src)
    local player = Bridge.GetPlayer(src)
    if not player then return nil end

    if framework == 'esx' then
        return player.job.name, player.job.grade
    end
    return player.PlayerData.job.name, player.PlayerData.job.grade.level
end

No manifesto, carregue-o antes dos arquivos que o usam:

lua
server_scripts {
    'bridge.lua',
    'server.lua',
}

O script então lê assim, e nunca menciona um framework:

lua
RegisterNetEvent('my_script:pay', function()
    local src = source
    local job = Bridge.GetJob(src)
    if job == 'mechanic' then
        Bridge.AddCash(src, 100)
    end
end)

Adicione um bridge de cliente para notificações e dados de jogador do mesmo jeito. Quando você adiciona um novo framework, como QBox com qbx_core, você adiciona um branch no bridge, e o script fica como está.

Lembre-se que um bridge só funciona se o framework inicia primeiro. Coloque ensure es_extended ou ensure qb-core acima do script em server.cfg, e leia ESX is nil se o objeto volta nil.

Checklist

Sintoma Solução
attempt to index a nil value (global 'ESX') em QBCore Uma chamada ESX ficou; substitua-a pelo mapa acima
Dinheiro ou job sempre nil Você lê PlayerData em ESX, ou xPlayer.job em QBCore
Erros de contagem de item em QBCore GetItemByName retorna nil quando o jogador não tem nenhum; verifique primeiro
Tabela errada em uma query users e identifier em ESX, players e citizenid em QBCore
Callback retorna nada Use as chamadas de register e trigger correspondentes para o framework
Precisa de ambos os frameworks Mova toda chamada de framework para um arquivo bridge

Respostas rápidas

Posso converter qualquer script ESX para QBCore?

Scripts que apenas usam o framework para jogadores, dinheiro, jobs, itens e notificações se convertem bem. Scripts construídos ao redor de recursos específicos do framework, como esx_society ou qb-management, precisam daquelas partes reescritas também.

O banco de dados muda quando mudo de framework?

Sim. ESX armazena jogadores em users com um identifier, e QBCore em players com um citizenid. Queries e nomes de tabela no script devem seguir o framework que você executa.

Um arquivo bridge é melhor que converter?

Se você precisa do script em ambos os frameworks, sim: você muda um arquivo, não o script inteiro. Se você apenas executa um framework, converta uma vez e descarte o outro branch.

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 →Advanced BoostingBoosting de veículos pelo tablet: contratos da classe D à S+, crews e fila ao vivo.Ver script →

Continue lendo