Преобразование ESX скрипта в QBCore (и обратно): карта функций и мост

Портируйте FiveM скрипт между ESX и QBCore: таблица общих вызовов (игрок, деньги, работа, предметы, уведомления, обратные вызовы) и файл моста, который поддерживает оба.

У вас есть скрипт, написанный для ESX, и ваш сервер запускает QBCore, или наоборот. Большинство скрипта — это простой Lua и natives, которые не меняются. Только вызовы фреймворка, и их меньше, чем вы ожидаете. Эта статья даёт вам карту их, а затем показывает, как изолировать их в один файл моста.

Что остаётся и что меняется

Natives, NUI, ваши собственные события, циклы, targets и меню работают на любом фреймворке. Что меняется, так это короткий список:

  • как вы получаете объект фреймворка
  • как вы получаете игрока
  • деньги, работы и предметы
  • уведомления
  • используемые предметы и обратные вызовы
  • таблицы базы данных для игроков

Ищите в скрипте ESX. и xPlayer, и каждое попадание — это что-то для преобразования.

Карта функций

Задача ESX Legacy QBCore
Получить объект ESX = exports['es_extended']:getSharedObject() local QBCore = exports['qb-core']:GetCoreObject()
Получить игрока (сервер) ESX.GetPlayerFromId(src) QBCore.Functions.GetPlayer(src)
Идентификатор игрока xPlayer.identifier Player.PlayerData.citizenid
Баланс наличных xPlayer.getMoney() Player.PlayerData.money.cash
Добавить наличные xPlayer.addMoney(n) Player.Functions.AddMoney('cash', n)
Удалить наличные xPlayer.removeMoney(n) Player.Functions.RemoveMoney('cash', n)
Добавить в банк xPlayer.addAccountMoney('bank', n) Player.Functions.AddMoney('bank', n)
Удалить из банка xPlayer.removeAccountMoney('bank', n) Player.Functions.RemoveMoney('bank', n)
Имя работы xPlayer.job.name Player.PlayerData.job.name
Уровень работы xPlayer.job.grade Player.PlayerData.job.grade.level
Добавить предмет xPlayer.addInventoryItem(name, n) Player.Functions.AddItem(name, n)
Удалить предмет xPlayer.removeInventoryItem(name, n) Player.Functions.RemoveItem(name, n)
Количество предметов xPlayer.getInventoryItem(name).count Player.Functions.GetItemByName(name) (nil если нет, затем .amount)
Используемый предмет ESX.RegisterUsableItem(name, function(src) end) QBCore.Functions.CreateUseableItem(name, function(src, item) end)
Уведомить (клиент) ESX.ShowNotification(msg) QBCore.Functions.Notify(msg, 'success')
Уведомить (сервер) xPlayer.showNotification(msg) TriggerClientEvent('QBCore:Notify', src, msg, 'success')
Данные игрока (клиент) ESX.GetPlayerData() QBCore.Functions.GetPlayerData()
Событие загрузки игрока esx:playerLoaded QBCore:Client:OnPlayerLoaded
Событие изменения работы esx:setJob QBCore:Client:OnJobUpdate
Обратный вызов сервера ESX.RegisterServerCallback QBCore.Functions.CreateCallback

Два деталя сбивают людей с толку. Типы денег: ESX имеет money для наличных и bank, QBCore использует 'cash' и 'bank' как первый аргумент. И уровень: ESX даёт простое число, QBCore таблицу, поэтому job.grade.level.

Обратные вызовы, которые использует каждый второй скрипт, сравниваются в деталях в server callbacks on ESX, QBCore and ox_lib.

База данных

Таблицы игроков отличаются, поэтому любой SELECT или UPDATE на них требует изменения:

ESX QBCore
Игроки users players
Ключ игрока identifier (строка license:) citizenid
Транспортные средства owned_vehicles player_vehicles

Скрипт, который хранит свои собственные данные, с его собственными таблицами, обычно продолжает работать, пока он ключирует строки на значение, которое вы можете получить от любого фреймворка. Использование license идентификатора для этого работает на обоих.

QBox

QBox ближе к QBCore, чем к ESX. Его ядро — qbx_core, оно содержит слой совместимости для exports['qb-core']:GetCoreObject(), и его инвентарь — ox_inventory. Скрипт, преобразованный в QBCore, обычно запускается на QBox с небольшими изменениями, кроме вызовов инвентаря.

Подход файла моста

Если скрипт должен работать на обоих, не размещайте его if ESX then ... else ... end. Поместите каждый вызов фреймворка в один файл, и пусть остальной скрипт вызывает этот файл.

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

В манифесте, загрузите его перед файлами, которые его используют:

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

Затем скрипт читается так и никогда не упоминает фреймворк:

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

Добавьте клиентский мост для уведомлений и данных игрока так же. Когда вы добавляете новый фреймворк, такой как QBox с qbx_core, вы добавляете ветвь в мост, и скрипт остаётся так же.

Помните, что мост работает только если фреймворк запускается первым. Поместите ensure es_extended или ensure qb-core выше скрипта в server.cfg, и читайте ESX is nil, если объект приходит обратно nil.

Контрольный список

Проблема Решение
attempt to index a nil value (global 'ESX') на QBCore Вызов ESX остался; замените его из карты выше
Деньги или работа всегда nil Вы читаете PlayerData на ESX, или xPlayer.job на QBCore
Ошибки количества предметов на QBCore GetItemByName возвращает nil, когда у игрока нет ни одного; проверьте первым
Неправильная таблица в запросе users и identifier на ESX, players и citizenid на QBCore
Обратный вызов возвращает ничего Используйте совпадающие регистр и вызовы триггера для фреймворка
Требуется оба фреймворка Переместите каждый вызов фреймворка в файл моста

Короткие ответы

Могу ли я преобразовать любой ESX скрипт в QBCore?

Скрипты, которые используют фреймворк только для игроков, денег, работ, предметов и уведомлений, преобразуются хорошо. Скрипты, построенные вокруг ресурсов фреймворка, таких как esx_society или qb-management, требуют переписывания и этих частей.

Меняется ли база данных, когда я переключаюсь на фреймворк?

Да. ESX хранит игроков в users с identifier, а QBCore в players с citizenid. Запросы и имена таблиц в скрипте должны следовать фреймворку, который вы запускаете.

Лучше ли файл моста, чем преобразование?

Если вам нужен скрипт на обоих фреймворках, да: вы меняете один файл, не весь скрипт. Если вы запускаете только один фреймворк, преобразуйте один раз и отбросьте другую ветвь.

Скрипты без этой проблемы

Item Creator V2Создавайте используемые предметы с анимациями, пропами, эффектами и не только — без кода.Смотреть скрипт →Shop CreatorМагазин меньше чем за минуту — владельцы, сотрудники, сейфы и ограбления в комплекте.Смотреть скрипт →Advanced BoostingУгон машин на заказ через планшет: контракты от класса D до S+, команды и живая очередь.Смотреть скрипт →

Читайте также