Преобразование QBCore скрипта в QBox: qbx_core, ox_inventory, ox_target

Как портировать QBCore скрипт в QBox: слой совместимости qbx_core, GetPlayer, ox_inventory предметы, ox_lib уведомления и прогресс, ox_target, и что обычно ломается.

У вас есть скрипт, написанный для QBCore и сервер, запускающий QBox. Иногда он запускается и работает, иногда консоль заполняется ошибками о отсутствующем qb-inventory, qb-target или qb-menu. Вот порядок для его портирования и места, где он обычно ломается.

Если вы всё ещё выбираете ядро, то же самое задание с другого направления находится в преобразование ESX скрипта в QBCore.

Что QBox меняет и что он сохраняет

QBox построен на qbx_core плюс ресурсы Overextended: ox_lib, oxmysql, ox_inventory и ox_target. Он сохраняет слой совместимости, поэтому exports['qb-core']:GetCoreObject() всё ещё отвечает и PlayerData имеет ту же форму (citizenid, job, charinfo, metadata, money). Вот почему многие скрипты запускаются без изменений.

Что он не сохраняет, так это старые QB служебные ресурсы. Где QBCore использовал qb-inventory, qb-target, qb-menu, qb-input и qb-progressbar, QBox ожидает ox_inventory, ox_target и ox_lib. Это куски, которые вы портируете.

Первый шаг — убедиться, что ядро запущено правильно:

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

Удалите любую оставшуюся папку qb-core, так как два ядра конфликтуют. См. QBCore is nil: GetCoreObject, если объект отсутствует.

Шаг 1: зависимости в манифесте

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 — это то, что даёт вам глобальный lib. Если это не найдено, см. ox_lib init.lua не найден.

Шаг 2: получение игрока

Оба эти работают на QBox. Первый — стиль совместимости, второй — способ 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

Оба возвращают nil для игрока, который не загружен, поэтому сохраняйте nil проверку. Чтобы найти загруженного игрока по citizen id, QBox также имеет GetPlayerByCitizenId. Когда вы портируете, вы можете оставить вызовы QBCore на месте и заменить их один за другим позже.

Шаг 3: инвентарь

Это то, где большинство скриптов ломается. qb-inventory и ox_inventory не делятся определениями предметов или именами функций.

Задача QBCore QBox с ox_inventory
Добавить предмет Player.Functions.AddItem('water', 1) exports.ox_inventory:AddItem(source, 'water', 1)
Удалить предмет Player.Functions.RemoveItem('water', 1) exports.ox_inventory:RemoveItem(source, 'water', 1)
Количество Player.Functions.GetItemByName('water').amount exports.ox_inventory:GetItemCount(source, 'water')
Метаданные таблица info таблица 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 возвращает ложное значение, когда предмет не существует или не может быть переносимым, поэтому проверьте это. Определения предметов тоже переходят. QBCore хранит их в qb-core/shared/items.lua, ox_inventory в ox_inventory/data/items.lua. Добавьте каждый предмет, который скрипт использует там, в формате ox_inventory. Как это сделать находится в добавить предметы в ox_inventory, и формат QBCore, из которого вы приходите, находится в добавить предметы в qb-inventory.

Используемые предметы также регистрируются иначе: QBCore.Functions.CreateUseableItem становится export, установленным в определении предмета в ox_inventory, который указывает на функцию в вашем скрипте. Вызовы QBCore могут всё ещё работать через слой совместимости, поэтому протестируйте предмет перед его переписыванием.

Шаг 4: уведомления, прогресс и меню с ox_lib

ox_lib заменяет отдельные QB служебные ресурсы. Вызовы близки к тому, что вы знаете:

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

Меню переходят из qb-menu в lib.registerContext и lib.showContext, и формы ввода из qb-input в lib.inputDialog. Полные примеры находятся в уведомления и полосы прогресса на ESX, QBCore и ox_lib и ox_lib контекстные меню.

Шаг 5: ox_target вместо qb-target

qb-target принимает имя, координаты и таблицу опций в его собственном макете. ox_target принимает одну таблицу:

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

Обратите внимание event становится onSelect (или event всё ещё работает для события клиента), и job становится groups. Детали находятся в qb-target vs ox_target и ox_target зоны.

Что обычно ломается

  • Ошибки отсутствующих предметов. Предмет существует в общем файле qb-core, но не в ox_inventory. Добавьте его.
  • No such export для qb-inventory, qb-target или qb-menu. Скрипт вызывает их напрямую: портируйте те вызовы, или он никогда не запустится.
  • Обратные вызовы. lib.callback — это стиль QBox. Если скрипт всё ещё использует QBCore.Functions.CreateCallback, протестируйте его и переместите его в ox_lib, если он не удаётся: см. server callbacks.
  • Работы и банды с уровнями. QBox имеет свои собственные данные работы и группы. Протестируйте каждую проверку работы, особенно on-duty и сравнения уровней.
  • Смешанные ядра. Оставшийся ресурс qb-core запущен рядом с qbx_core.
  • Порядок запуска. Ваш скрипт выше ox_lib, ox_inventory или qbx_core в server.cfg.

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

Проблема Решение
GetCoreObject nil Запустите qbx_core сначала и удалите любую папку qb-core
No such export для qb-inventory Используйте exports.ox_inventory:AddItem(source, item, count)
Предмет не найден Добавьте его в ox_inventory/data/items.lua
Вызовы qb-target не удаются Портируйте в exports.ox_target:addBoxZone или addLocalEntity
lib nil Добавьте shared_script '@ox_lib/init.lua'
Проверка работы всегда false Протестируйте PlayerData.job.name и уровень на QBox

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

Работают ли QBCore скрипты на QBox без изменений?

Многие работают, потому что qbx_core имеет слой совместимости для qb-core. Скрипты, которые зависят от qb-inventory, qb-target или qb-menu, обычно требуют работы, так как QBox использует ox_inventory, ox_target и ox_lib вместо этого.

Как я получаю игрока на QBox?

На сервере, exports.qbx_core:GetPlayer(source) возвращает игрока, с той же таблицей PlayerData, которую вы знаете из QBCore.

Нужно ли мне переписывать всё, чтобы переместиться на QBox?

Нет. Запустите скрипт на QBox, читайте ошибки, и замените куски, которые не удаются: инвентарь, target, меню и уведомления. Остальное, такое как PlayerData, работы и метаданные, сохраняет свою форму.

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

Item Creator V2Создавайте используемые предметы с анимациями, пропами, эффектами и не только — без кода.Смотреть скрипт →Shop CreatorМагазин меньше чем за минуту — владельцы, сотрудники, сейфы и ограбления в комплекте.Смотреть скрипт →Quest CreatorВизуальный редактор квестов и диалогов с NPC — узел за узлом прямо в игре.Смотреть скрипт →

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