Перенос сервера с QBCore на Qbox - это в основном работа с базой данных и инвентарём, а не со скриптами. qbx_core объявляет provide 'qb-core' и содержит мост, который отвечает на старые вызовы exports['qb-core']:GetCoreObject(), поэтому большинство ресурсов qb-* для работ, магазинов и HUD запускаются без правок. Не переносится qb-inventory: Qbox работает только с ox_inventory и отказывается запускаться, пока работает qb-inventory, поэтому описания предметов, инвентарь каждого игрока, а также ваши stash, багажники и бардачки нужно конвертировать. Кроме того, qbx_core.sql меняет таблицу players и добавляет таблицу player_groups для multijob. Сначала сделайте всё это на копии сервера и базы, не трогайте старую папку resources/ и дамп базы - и сам переход займёт вечер, а не неделю.
Какой фреймворк выбрать и чем они отличаются, разобрано в статье FiveM frameworks: ESX vs QBCore vs Qbox. Здесь предполагается, что вы уже определились и у вас работает сервер на QBCore с реальными данными игроков, которые вы не хотите потерять.
Что на самом деле меняется между QBCore и Qbox#
Qbox - это продолжение QBCore, а не переписанный с нуля фреймворк, поэтому миграция вообще возможна. У объекта игрока по-прежнему есть PlayerData, citizenid, charinfo, money, job и gang. Таблица players сохранила имя и большинство столбцов. Изменилось всё, что находится вокруг ядра.
| Область | QBCore | Qbox |
|---|---|---|
| Ресурс ядра | qb-core | qbx_core (также отвечает как qb-core) |
| Инвентарь | qb-inventory | ox_inventory, и ничего другого |
| Список предметов | qb-core/shared/items.lua | ox_inventory/data/items.lua |
| Работы и банды | shared/jobs.lua, gangs.lua | те же файлы, числовые ключи рангов |
| Multijob | внешний ресурс | встроен, таблица player_groups |
| Мультиперсонаж | qb-multicharacter | встроен в qbx_core |
| Target, меню, ввод | qb-target, qb-menu, qb-input | ox_target и ox_lib |
Основная часть вашей работы прячется в последних трёх строках. Qbox также требует, чтобы ox_lib и oxmysql были запущены первыми, чтобы был включён OneSync и использовалась свежая сборка FXServer. В манифесте текущей версии qbx_core в зависимостях указан /server:10731, а значит, на более старом артефакте он не запустится. Это число меняется от релиза к релизу, поэтому смотрите fxmanifest.lua в скачанной версии, а если ваш сервер отстаёт, читайте FiveM server updates and artifacts.
Как работает мост qb-core и где он заканчивается#
Мост - это набор файлов в qbx_core/bridge/qb/, которые собирают старый объект QBCore из собственных функций Qbox. Поскольку в манифесте qbx_core объявлено provide 'qb-core', ресурс, у которого qb-core указан в зависимостях, считается удовлетворённым, а exports['qb-core']:GetCoreObject() возвращает нечто, похожее на объект QBCore. Мост включён по умолчанию и управляется одной convar:
setr qbx:enableBridge "true"Что продолжает работать через мост:
QBCore.Functions.GetPlayer(source)и методы игрока, которые от неё отходят:AddMoney,RemoveMoney,SetJob,SetMetaDataи остальные.- Обычные серверные и клиентные события, которые слушает ресурс работы, например
QBCore:Client:OnPlayerLoaded. QBCore.Shared.Jobs,GangsиVehicles, которые читаются из собственных файлов Qbox.- Старые экспорты drawtext,
exports['qb-core']:DrawText()иHideText(), теперь привязанные к текстовому UI изox_lib. - Функции предметов у игрока, такие как
Player.Functions.AddItemиRemoveItem: мост передаёт их вox_inventoryи переводит данные между двумя форматами предметов.
В документации Qbox фреймворк описан как примерно на 99% совместимый со скриптами QB, и для объекта ядра это справедливо. Мост заканчивается там, где код выходит за пределы ядра:
- Всё, что напрямую обращается к `qb-inventory`. На
exports['qb-inventory']:..., событиеinventory:server:OpenInventoryи события stash из qb-inventory никто не отвечает. Собственные функции инвентаря в мосте проверяют, чтоqb-inventoryне запущен, и падают с ошибкойqb-inventory is not compatible with qbx_core. use ox_inventory instead. - `Player.Functions.SetInventory` явно не поддерживается и вызывает ошибку. Скрипты, которые перезаписывают инвентарь целиком, нужно переделать на схему «очистить, затем добавить».
- Ресурсы, которые пишут SQL в таблицы QBCore, смысл которых изменился: старые таблицы stash, столбец job, который теперь перекрывает multijob, строки
player_vehicles, которые гаражный ресурс ожидает в определённом виде. - Внешние ресурсы multijob и multigang. В Qbox есть собственные, а в документации предупреждается, что непроверенные могут повредить данные. Удалите их до первого запуска.
- Экспорты `qb-target`.
ox_targetобеспечивает совместимость сqtarget, но не сqb-target. Ресурсу, который вызываетexports['qb-target']:AddBoxZone, нужен либо запущенныйqb-target, либо перевод наox_target.
Мост - это инструмент миграции, а не постоянный дом. В исходниках его функции помечены как устаревшие, а новый код должен обращаться к exports.qbx_core и ox_lib напрямую. Ресурсы можно переводить по одному, потому что вызовы через мост и нативные вызовы работают бок о бок.
Проведите аудит списка ресурсов, прежде чем что-либо трогать#
Откройте resources/ и разложите все папки в три стопки. Это час работы с текстовым файлом, и от него зависит, сколько времени займёт всё остальное.
- Работает без изменений. Ресурсы, которые используют только объект ядра, деньги игрока, работы и события. Большинство HUD, простые работы, магазины, продающие через
AddItem, эмоции, погода, голос. - Есть замена для Qbox или ox. Обычно это лучше, чем править код. Qbox поддерживает версии
qbx_для часто используемых ресурсов QB. - Нужно править или убирать. Всё, что обращается к
qb-inventory, активно используетqb-menuилиqb-inputлибо пишет собственный SQL в таблицы инвентаря и транспорта.
Замены, которые встречаются почти на каждом сервере:
| Ресурс QBCore | Аналог в Qbox | Примечание |
|---|---|---|
qb-inventory | ox_inventory | Обязательно, данные нужно конвертировать |
qb-target | ox_target | Зоны нужно переписать |
qb-menu, qb-input | ox_lib | Контекстные меню и диалоги ввода |
qb-doorlock | ox_doorlock | Двери вводятся заново |
qb-multicharacter | qbx_core | Встроен |
qb-garages | qbx_garages | Использует qbx_vehicles |
qb-vehiclekeys | qbx_vehiclekeys | |
qb-policejob | qbx_police | |
qb-ambulancejob | qbx_ambulancejob | Работает в паре с qbx_medical |
Интеграция ox_inventory с Qbox также проверяет, что запущен qbx_vehicles, так что добавьте его, даже если оставляете собственный гаражный ресурс. С платными скриптами не делайте предположений, а загляните на страницу автора: многие заявляют о поддержке Qbox через переключатель в конфиге, а скрипт с escrow, который вы не можете редактировать, либо поддерживает Qbox, либо нет. Что в таких скриптах можно менять, а что нельзя, описано в FiveM escrow and asset licensing.
Самый быстрый способ собрать третью стопку - поиск. Запустите это из папки resources/ на копии сервера и прочитайте каждое совпадение:
$ grep -rn --include=*.lua -e "qb-inventory" -e "qb-target" -e "SetInventory" .$ grep -rn --include=*.lua -e "stashitems" -e "trunkitems" -e "gloveboxitems" .$ grep -rn --include=*.lua -e "QBCore.Shared.Items\[" .Последний запрос важен, потому что некоторые ресурсы добавляют предметы во время работы, записывая их в QBCore.Shared.Items. В Qbox предметы принадлежат ox_inventory, и такие добавления на лету ничего полезного не делают.
Сначала соберите тестовый сервер#
Не мигрируйте рабочий сервер на месте. Соберите второй сервер, дайте ему копию базы данных и копию resources/ и сначала выполните все шаги ниже на нём. Общий метод - что копировать, что должно отличаться, насколько маленьким он может быть - описан в running a test server beside production. Для этой миграции в частности:
- Всегда отдельная база данных. Тестовый сервер должен указывать своим
mysql_connection_stringна копию, а не на боевую схему. Шаги SQL ниже изменяют таблицы, и случайный запуск их на живых данных - единственная ошибка, которая превращает вечер в выходные. - Свежий дамп боевой базы для наполнения. Используйте
mysqldumpс--single-transaction, чтобы не блокировать игроков на время выполнения, как описано в mysqldump backup and restore. - Закройте его от публики. Поставьте низкое значение
sv_maxclients, добавьте проверку вроде пароля через ваш whitelist в Discord или просто не публикуйте его в списке, и дайте ему отдельное имя хоста, чтобы никто не подключился не к тому серверу. - Заходите настоящим персонажем. Тест на новом персонаже ничего не доказывает про конвертацию. Выберите несколько персонажей с полным инвентарём, оружием, машиной с предметами в багажнике и рангом работы выше нуля и проверьте каждого после конвертации.
На RE:NODE каждый сервер - это отдельный контейнер со своим слотом базы данных, поэтому копия тестового сервера не видит боевую базу, пока вы не дадите ей эти учётные данные. Импортируйте дамп через «Open in phpMyAdmin» на вкладке базы данных тестового сервера или из командной строки, используя сгенерированные хост и пользователя.
Какие изменения в базе данных вносит Qbox#
Сначала сделайте резервную копию. Каждый шаг в этом разделе легко применить и неудобно отменять.
$ mysqldump --single-transaction --routines -h DB_HOST -u DB_USER -p qbcore \ > qbcore-before-qbox.sqlЗатем импортируйте qbx_core.sql из релиза qbx_core, который вы устанавливаете. На существующей базе QBCore он делает три важных вещи. Он добавляет в players столбец last_logged_out (а в текущих версиях ещё и userId). Он меняет players так, чтобы таблица и её ключевые столбцы использовали сортировку utf8mb4_unicode_ci. И он создаёт player_groups, где хранятся все работы и банды персонажа, с внешним ключом по citizenid на players.
Именно внешний ключ - то место, где застревает большинство миграций. Для внешнего ключа у обоих столбцов должна быть одна и та же сортировка, а многие базы QBCore созданы с utf8mb4_general_ci. Если импорт падает с ошибкой внешнего ключа, проверьте и исправьте сортировку:
SELECT TABLE_NAME, COLUMN_NAME, COLLATION_NAMEFROM information_schema.COLUMNSWHERE TABLE_SCHEMA = 'qbcore' AND COLUMN_NAME = 'citizenid';ALTER TABLE players MODIFY citizenid VARCHAR(50) NOT NULL COLLATE utf8mb4_unicode_ci;Выполните такой же MODIFY для любой другой таблицы, у которой столбец citizenid по-прежнему показывает utf8mb4_general_ci, сохранив у каждого столбца прежний тип и допустимость NULL, а затем импортируйте qbx_core.sql ещё раз. Почему сортировки вообще конфликтуют, описано в MySQL utf8mb4 and collations.
Дальше - работы и банды. Qbox ожидает, что ключи рангов в shared/jobs.lua и shared/gangs.lua будут числами, тогда как в QBCore это были строки:
police = { label = 'LSPD', defaultDuty = true, grades = { [0] = { name = 'Recruit', payment = 50 }, -- в QBCore было ['0'] [1] = { name = 'Officer', payment = 75 }, [4] = { name = 'Chief', isboss = true, payment = 150 }, },},Перенесите свои работы и банды до первого запуска, а затем заполните новую таблицу. При запущенном сервере введите это в консоли txAdmin или в живой консоли:
convertjobsКоманда копирует текущую работу и банду каждого персонажа из таблицы players в player_groups, запускается только из консоли сервера, и её безопасно запускать дважды. Поведение multijob после этого определяют две convar: qbx:max_jobs_per_player и qbx:max_gangs_per_player, обе по умолчанию равны 1.
player_vehicles не затрагивается: qbx_vehicles создаёт её, только если такой таблицы ещё нет. При первом запуске ox_inventory добавляет в неё столбцы trunk и glovebox, а в players - столбец inventory, если его нет.
Перевод qb-inventory на ox_inventory#
Это самая тонкая часть, и именно здесь руководства противоречат друг другу сильнее всего, потому что в 2024 году инструменты изменились. Переносятся три разные вещи: описания предметов, инвентари игроков и всё остальное (stash, багажники, бардачки).
Описания предметов
Вставьте вашу таблицу предметов QBCore в qbx_core/shared/items.lua. При следующем запуске мост конвертирует в формат ox_inventory каждый предмет, который ox_inventory ещё не знает, и записывает их в qbx_core/converted.lua, выводя в консоль предупреждение с количеством добавленных. Он пропускает имена, похожие на оружие, обвесы и патроны, потому что у ox_inventory есть собственные описания оружия. Проверьте файл, скопируйте записи в ox_inventory/data/items.lua, снова очистите shared/items.lua и перезапустите сервер. Конвертированная запись выглядит так:
['sandwich'] = { label = 'Sandwich', weight = 200, stack = true, close = true, description = 'Nice bread for your stomach', client = { status = { hunger = 200000 }, image = 'sandwich.png', },},Используемые предметы по-прежнему работают через CreateUseableItem в мосте, но значения голода и жажды из вашего ресурса с едой сами не применятся, поэтому проверьте каждый предмет еды в игре. Скопируйте картинки предметов из qb-inventory/html/images в ox_inventory/web/images, иначе все конвертированные предметы будут отображаться пустым квадратом.
Инвентари игроков
И QBCore, и ox_inventory хранят инвентарь игрока как JSON в players.inventory, но поля различаются:
{"name": "water_bottle", "amount": 3, "info": {}, "slot": 1, "type": "item"}{"name": "water_bottle", "count": 3, "metadata": {}, "slot": 1}Первая строка - QBCore, вторая - ox_inventory. Когда ox_inventory загружает неконвертированного персонажа, он останавливается с сообщением Inventory for player.X contains invalid data. Ensure you have converted inventories to the correct format. В текущих релизах ox_inventory есть консольная команда convertinventory, но её единственные варианты - esx и esxproperty; если запустить её без аргумента, она выведет этот список. Конвертер QBCore был удалён в августе 2024 года, а v2.41.0 - последний релиз, в котором есть convertinventory qb. Он переименовывал amount в count и info в metadata, превращал наличные QBCore в предмет money и выдавал оружию серийный номер и прочность на основе прежнего quality.
Практических путей два: один раз запустить этот старый релиз на тестовом сервере только ради конвертации, а потом заменить его актуальным ox_inventory, либо написать то же сопоставление полей самостоятельно на SQL или Lua. В любом случае сравните несколько персонажей до и после. После конвертации наличные хранятся в двух местах, которые ox_inventory синхронизирует: в предмете money и в PlayerData.money.cash.
Stash, багажники и бардачки
Именно здесь данные теряются чаще всего. Старые версии qb-inventory хранили их в stashitems, trunkitems и gloveboxitems; старый конвертер переносил багажники и бардачки в player_vehicles, но stash не обрабатывал вовсе. Текущий qb-inventory (2.x) хранит всё в одной таблице inventories с ключом - строкой identifier, и ни один официальный конвертер её не читает. В Qbox ox_inventory хранит stash в собственной таблице ox_inventory, а багажники и бардачки - в player_vehicles, с ключом по id транспорта.
Поэтому решите, что стоит сохранять. Личные и рабочие stash обычно стоит, и для них нужен небольшой скрипт, который читает каждую строку inventories, конвертирует предметы, как описано выше, и вставляет их под именем stash, которое используют ваши определения stash в ox_inventory. Многие серверы решают, что содержимое багажников и бардачков не стоит скрипта, и объявляют, что они будут очищены. Это законный выбор, но делайте его осознанно и предупредите игроков до переключения, а не после.
День перехода по порядку#
Когда тестовый сервер прошёл весь процесс и пережил сессию с настоящими тестировщиками, боевое переключение сводится к чек-листу:
- Объявите окно обслуживания и закройте сервер через whitelist в txAdmin или остановив его.
- Сделайте итоговый
mysqldumpи резервную копию файлов сервера в панели. Скачайте обе. - Выполните шаги SQL в том порядке, который сработал на тестовом сервере.
- Замените
resources/проверенной папкой и перенесите из неёserver.cfg,ox.cfgиpermissions.cfg. - Запускайте с открытой консолью.
ensure oxmysql,ox_lib,qbx_coreиox_inventoryдолжны подняться раньше всего, что от них зависит. На что смотреть, описано в Reading the console. - Выполните
convertjobsи ту конвертацию инвентаря, которую вы отрабатывали. - Зайдите тремя персонажами из тех, что вы проверяли на тестовом сервере. Откройте инвентарь, stash и багажник.
- Откройте сервер для игроков и первый час следите за консолью и
resmon.
План отката#
Запишите план отката до начала, потому что в тот момент, когда он понадобится, вы не сможете ясно мыслить. Миграция обратима, только если обе половины старого сервера остались нетронутыми.
- Файлы. Храните старую папку
resources/иserver.cfgкак архив, не перезаписывая их. Возврат назад - это восстановление этой папки. - База данных. Восстановите
qbcore-before-qbox.sqlв базу. Исправление вперёд - это не откат: конвертированный JSON инвентаря, новая сортировка иplayer_groupsсами не отменятся. - Крайний срок решения. Выберите момент, после которого вы исправляете вперёд, а не откатываетесь. У игроков, которые сутки играли на Qbox, есть данные, которые восстановление сотрёт. Разумное правило: откатывайтесь свободно в окно обслуживания и после него - только при потере данных.
На RE:NODE резервная копия в панели охватывает файлы, а дамп - базу данных, поэтому делайте обе. Резервную копию можно заблокировать от ротации, чтобы копия перед миграцией пережила ваши запланированные бэкапы, но проверьте восстановление на тестовом сервере, прежде чем на него полагаться.
Устранение неполадок#
Ошибки, которые возникают почти при каждой миграции:
| Симптом | Причина |
|---|---|
qb-inventory is not compatible with qbx_core | qb-inventory всё ещё запущен |
contains invalid data при входе | Инвентарь всё ещё в формате QBCore |
Ошибка внешнего ключа при импорте qbx_core.sql | Сортировки citizenid различаются |
| Ранг работы показывает nil | Ключи рангов всё ещё строки |
| Предметы отображаются пустыми квадратами | Картинки не скопированы |
| Игроки потеряли работу | cleanPlayerGroups включён, а работ не хватает |
Ещё две проблемы менее заметны. Ресурс, который молча ничего не делает, обычно обращается к QBCore.Shared.Items, чтобы проверить существование предмета; замените эту проверку на exports.ox_inventory:Items(). А дублирующиеся папки - старый qb-inventory в забытой папке в квадратных скобках - запускают то, что FXServer найдёт первым, поэтому удалите старую папку, а не оставляйте её без ensure.
FAQ#
Можно ли запускать Qbox без моста qb-core?
Да, установите qbx:enableBridge в false, но только когда на сервере ничего больше не обращается к qb-core. Большинство серверов держат его включённым месяцами и переводят ресурсы постепенно.
Потеряю ли я данные персонажей при переходе на Qbox?
Нет, если конвертировать правильно. Персонажи, деньги, метаданные, работы и транспорт остаются в тех же таблицах. Под угрозой инвентари, stash, багажники и бардачки, потому что у них меняются формат и таблицы.
Можно ли оставить qb-inventory на Qbox?
Нет. qbx_core отказывается работать при запущенном qb-inventory, а ox_inventory - единственный инвентарь, который поддерживает Qbox.
Будут ли мои платные скрипты QBCore работать на Qbox?
Многие работают через мост, и многие авторы выпускают вариант для Qbox. Ломаются те, что напрямую обращаются к qb-inventory или qb-target. Проверьте заметки автора и протестируйте на копии.
Сколько занимает миграция?
Для сервера с умеренным списком ресурсов - выходные на подготовку на тестовом сервере и окно обслуживания в один-два часа. Большие серверы с десятками скриптов, зависящих от инвентаря, требуют больше времени, в основном на переписывание этих скриптов.
Можно ли вернуться на QBCore после перехода?
Только восстановив дамп базы до миграции и старую папку resources/, что сотрёт всё, что игроки сделали после переключения. Определите крайний срок отката до начала.


