RE:NODE

Migrace z QBCore na Qbox: bridge, inventář a databáze

Text: Tým RE:NODE
14 min čtení


Přechod ze QBCore na Qbox je hlavně práce s databází a inventářem, ne se skripty. qbx_core deklaruje provide 'qb-core' a obsahuje bridge, který odpovídá na staré volání exports['qb-core']:GetCoreObject(), takže většina resourců qb-* pro práce, obchody a HUD naběhne bez úprav. Co se nepřenese, je qb-inventory: Qbox běží pouze na ox_inventory a odmítne fungovat, když je spuštěné qb-inventory, takže je potřeba převést definice itemů, inventář každého hráče i vaše stashe, kufry a přihrádky v autech. Navíc qbx_core.sql mění tabulku players a přidává tabulku player_groups pro multijob. Všechno nejdřív udělej na kopii serveru a databáze, starou složku resources/ a dump databáze nech nedotčené a samotný přechod je pak práce na jeden večer, ne na týden.

O tom, který framework vůbec zvolit a čím se jednotlivé liší, se píše v článku FiveM frameworky: ESX vs QBCore vs Qbox. Tento článek předpokládá, že ses už rozhodl a máš běžící QBCore server se skutečnými daty hráčů, o která nechceš přijít.

Co se mezi QBCore a Qbox vlastně mění#

Qbox je pokračování QBCore, ne přepis od nuly, a proto je migrace vůbec možná. Objekt hráče pořád obsahuje PlayerData, citizenid, charinfo, money, job a gang. Tabulka players si zachovala název i většinu sloupců. Změnilo se všechno okolo jádra.

OblastQBCoreQbox
Jádroqb-coreqbx_core (odpovídá i jako qb-core)
Inventářqb-inventoryox_inventory, nic jiného
Seznam itemůqb-core/shared/items.luaox_inventory/data/items.lua
Práce a gangyshared/jobs.lua, gangs.luastejné soubory, číselné klíče gradů
Multijobexterní resourcezabudovaný, tabulka player_groups
Více postavqb-multicharacterzabudované v qbx_core
Target, menu, inputqb-target, qb-menu, qb-inputox_target a ox_lib

V posledních třech řádcích se skrývá většina práce. Qbox navíc vyžaduje, aby před ním běžely ox_lib a oxmysql, zapnuté OneSync a nedávný build FXServeru. Aktuální manifest qbx_core uvádí jako závislost /server:10731, což znamená, že na starším artefaktu nenaběhne - číslo se s vydáními posouvá, takže si přečti fxmanifest.lua ve verzi, kterou stahuješ, a pokud tvůj server zaostává, podívej se na aktualizace a artefakty FiveM serveru.

Jak funguje bridge qb-core a kde končí#

Bridge je sada souborů v qbx_core/bridge/qb/, která z vlastních funkcí Qboxu skládá starý objekt QBCore. Protože qbx_core ve svém manifestu deklaruje provide 'qb-core', resource, který uvádí qb-core jako závislost, je spokojený a exports['qb-core']:GetCoreObject() vrací něco, co vypadá jako objekt QBCore. Bridge je ve výchozím stavu zapnutý a řídí ho jediný convar:

server.cfg
setr qbx:enableBridge "true"

Co přes bridge dál funguje:

  • QBCore.Functions.GetPlayer(source) a metody hráče, které na něm visí: AddMoney, RemoveMoney, SetJob, SetMetaData a další.
  • Obvyklé serverové a klientské eventy, které poslouchá resource pro práci, například QBCore:Client:OnPlayerLoaded.
  • QBCore.Shared.Jobs, Gangs a Vehicles, čtené z vlastních souborů Qboxu.
  • Staré drawtext exporty, exports['qb-core']:DrawText() a HideText(), nyní namapované na text UI z ox_lib.
  • Funkce pro itemy na hráči, například Player.Functions.AddItem a RemoveItem, které bridge předává do ox_inventory a překládá mezi oběma formáty itemů.

Dokumentace Qboxu popisuje framework jako zhruba z 99 % kompatibilní se skripty pro QB a pro objekt jádra je to férové tvrzení. Končí to u všeho, co sahá za jádro:

  • Cokoli, co volá `qb-inventory` přímo. exports['qb-inventory']:..., event inventory:server:OpenInventory a stash eventy z qb-inventory nemají kdo obsloužit. Vlastní inventářové funkce bridge ověřují, že qb-inventory neběží, a jinak selžou s chybou qb-inventory is not compatible with qbx_core. use ox_inventory instead.
  • `Player.Functions.SetInventory` je výslovně nepodporované a vyhodí chybu. Skripty, které přepisují celý inventář, je potřeba změnit na postup nejdřív vymazat, pak přidat.
  • Resourcy, které píšou SQL proti tabulkám QBCore, jež už neznamenají totéž - staré tabulky stashů, sloupec s prací, který nově překrývá multijob, řádky player_vehicles, které garážový resource očekává v určitém tvaru.
  • Externí resourcy pro multijob a multigang. Qbox má vlastní a dokumentace varuje, že neověřené mohou poškodit data. Odstraň je před prvním startem.
  • Exporty `qb-target`. ox_target poskytuje kompatibilitu pro qtarget, ne pro qb-target. Resource, který volá exports['qb-target']:AddBoxZone, potřebuje buď stále běžící qb-target, nebo převod na ox_target.

Bridge je nástroj pro migraci, ne trvalý domov. Jeho funkce jsou ve zdrojovém kódu označené jako zastaralé a nový kód by měl volat exports.qbx_core a ox_lib přímo. Resourcy můžeš převádět po jednom, protože bridgovaná a nativní volání fungují vedle sebe.

Před jakýmkoli zásahem projdi seznam resourců#

Otevři resources/ a roztřiď každou složku do tří hromádek. Je to hodina práce s textovým souborem a rozhoduje o tom, jak dlouho potrvá zbytek.

  1. Funguje beze změn. Resourcy, které používají jen objekt jádra, peníze hráče, práce a eventy. Většina HUDů, jednoduché práce, obchody prodávající přes AddItem, emoty, počasí, voice.
  2. Má náhradu v Qboxu nebo ox. Obvykle lepší cesta než záplatování. Qbox udržuje verze qbx_ běžně používaných resourců z QB.
  3. Potřebuje úpravu nebo vyřadit. Cokoli, co komunikuje s qb-inventory, výrazně využívá qb-menu nebo qb-input, nebo píše vlastní SQL proti tabulkám inventáře a vozidel.

Náhrady, které se řeší téměř na každém serveru:

Resource z QBCoreStrana QboxuPoznámka
qb-inventoryox_inventoryPovinné, data je nutné převést
qb-targetox_targetZóny je třeba přepsat
qb-menu, qb-inputox_libKontextová menu a vstupní dialogy
qb-doorlockox_doorlockDveře se zadávají znovu
qb-multicharacterqbx_coreZabudované
qb-garagesqbx_garagesPoužívá qbx_vehicles
qb-vehiclekeysqbx_vehiclekeys
qb-policejobqbx_police
qb-ambulancejobqbx_ambulancejobSpolupracuje s qbx_medical

Integrace ox_inventory pro Qbox také ověřuje, že běží qbx_vehicles, takže ho přidej, i když si necháš vlastní garážový resource. U placených skriptů se před jakýmkoli předpokladem podívej na stránku autora: mnohé inzerují podporu Qboxu přes přepínač v konfiguraci a escrow skript, který nemůžeš upravit, Qbox buď podporuje, nebo ne. Co v nich můžeš a nemůžeš měnit, popisuje FiveM escrow a licencování assetů.

Nejrychlejší způsob, jak sestavit třetí hromádku, je vyhledávání. Spusť tohle ve složce resources/ na kopii serveru a projdi každý nález:

bash
$ 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\[" .

Poslední příkaz je důležitý, protože některé resourcy přidávají itemy za běhu zápisem do QBCore.Shared.Items. V Qboxu itemy patří ox_inventory a tato přidání za běhu nedělají nic užitečného.

Nejdřív postav testovací server#

Nemigruj živý server na místě. Postav druhý server, dej mu kopii databáze a kopii resources/ a každý krok níže udělej nejdřív tam. Obecný postup - co kopírovat, co se musí lišit, jak malý může být - je v článku testovací server vedle produkčního. Pro tuto migraci konkrétně:

  • Vždy samostatná databáze. Testovací server musí mít mysql_connection_string namířený na kopii, nikdy na produkční schéma. SQL kroky níže upravují tabulky a jejich omylné spuštění nad živými daty je jediná chyba, která změní večer ve ztracený víkend.
  • Čerstvý dump produkce jako základ. Použij mysqldump s --single-transaction, aby ses při běhu nezamkl hráče venku, jak je popsáno v zálohování a obnově pomocí mysqldump.
  • Zavři ho veřejnosti. Nastav nízké sv_maxclients, přidej kontrolu přes whitelist na Discordu nebo ho prostě nevypisuj a dej mu vlastní hostname, aby se nikdo nepřipojil na špatný.
  • Přihlas se jako skutečná postava. Testování na nové postavě o převodu nic nedokazuje. Vyber několik postav s plným inventářem, zbraněmi, autem s věcmi v kufru a prací s gradem nad nulou a po převodu zkontroluj každou z nich.

Na RE:NODE je každý server vlastní kontejner s vlastním slotem databáze, takže kopie testovacího serveru produkční databázi nevidí, pokud jí nedáš její přihlašovací údaje. Dump naimportuj přes „Open in phpMyAdmin“ na záložce databáze testovacího serveru, nebo z příkazové řádky s vygenerovaným hostem a uživatelem.

Změny v databázi, které Qbox dělá#

Nejdřív zálohuj. Každý krok v této části se snadno provede a těžko vrací.

bash
$ mysqldump --single-transaction --routines -h DB_HOST -u DB_USER -p qbcore \    > qbcore-before-qbox.sql

Pak naimportuj qbx_core.sql z vydání qbx_core, které instaluješ. Proti existující databázi QBCore dělá tři důležité věci. Přidá do players sloupec last_logged_out (a v aktuálních verzích i sloupec userId). Změní players tak, aby tabulka a její klíčové sloupce používaly collation utf8mb4_unicode_ci. A vytvoří player_groups, kde je uložená každá práce a gang, které postava má, s cizím klíčem na citizenid zpět do players.

Právě tento cizí klíč je místo, kde většina migrací uvízne. Cizí klíč vyžaduje, aby oba sloupce používaly stejnou collation, a spousta databází QBCore byla vytvořena s utf8mb4_general_ci. Pokud import selže s chybou cizího klíče, zkontroluj a oprav collation:

sql
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;

Stejné MODIFY spusť na každé další tabulce, jejíž sloupec citizenid stále hlásí utf8mb4_general_ci, a ponech každému sloupci jeho stávající typ a nullabilitu, pak qbx_core.sql naimportuj znovu. Proč se collation vůbec střetávají, vysvětluje MySQL utf8mb4 a collation.

Dále práce a gangy. Qbox chce klíče gradů v shared/jobs.lua a shared/gangs.lua jako čísla, zatímco QBCore používal řetězce:

qbx_core/shared/jobs.lua
police = {    label = 'LSPD',    defaultDuty = true,    grades = {        [0] = { name = 'Recruit', payment = 50 },      -- QBCore had ['0']        [1] = { name = 'Officer', payment = 75 },        [4] = { name = 'Chief', isboss = true, payment = 150 },    },},

Vlastní práce a gangy přenes před prvním startem, pak naplň novou tabulku. Na běžícím serveru napiš do konzole txAdmin nebo do živé konzole tohle:

code
convertjobs

Příkaz zkopíruje aktuální práci a gang každé postavy z tabulky players do player_groups, jde spustit jen z konzole serveru a je bezpečné ho spustit dvakrát. Chování multijobu pak určují dva convary: qbx:max_jobs_per_player a qbx:max_gangs_per_player, oba ve výchozím stavu 1.

player_vehicles zůstává nedotčená: qbx_vehicles ji vytvoří, jen pokud neexistuje. ox_inventory při prvním startu přidá do ní sloupce trunk a glovebox a do players sloupec inventory, pokud chybí.

Převod qb-inventory na ox_inventory#

Tady je potřeba největší opatrnosti a právě tady se návody nejvíc rozcházejí, protože se v roce 2024 změnily nástroje. Přesouvají se tři oddělené věci: definice itemů, inventáře hráčů a všechno ostatní (stashe, kufry, přihrádky).

Definice itemů

Vlož svou tabulku itemů z QBCore do qbx_core/shared/items.lua. Při dalším startu bridge převede každý item, který ox_inventory ještě nezná, do formátu ox_inventory a zapíše je do qbx_core/converted.lua, přičemž konzole varováním oznámí, kolik jich přidal. Přeskočí názvy, které vypadají jako zbraně, nástavby a munice, protože ox_inventory má vlastní definice zbraní. Soubor zkontroluj, záznamy zkopíruj do ox_inventory/data/items.lua, shared/items.lua zase vyprázdni a restartuj. Převedený záznam vypadá takto:

ox_inventory/data/items.lua
['sandwich'] = {    label = 'Sandwich',    weight = 200,    stack = true,    close = true,    description = 'Nice bread for your stomach',    client = {        status = { hunger = 200000 },        image = 'sandwich.png',    },},

Použitelné itemy dál fungují přes CreateUseableItem z bridge, ale hodnoty hladu a žízně z tvého resourcu pro jídlo a pití se samy neuplatní; každý item s jídlem jednou vyzkoušej ve hře. Obrázky itemů zkopíruj z qb-inventory/html/images do ox_inventory/web/images, jinak se každý převedený item zobrazí jako prázdný čtverec.

Inventáře hráčů

QBCore i ox_inventory ukládají inventář hráče jako JSON do players.inventory, ale pole se liší:

json
{"name": "water_bottle", "amount": 3, "info": {}, "slot": 1, "type": "item"}{"name": "water_bottle", "count": 3, "metadata": {}, "slot": 1}

První řádek je QBCore, druhý ox_inventory. Když ox_inventory načte nepřevedenou postavu, zastaví se s hláškou Inventory for player.X contains invalid data. Ensure you have converted inventories to the correct format. Aktuální vydání ox_inventory obsahují konzolový příkaz convertinventory, ale jeho jedinými možnostmi jsou esx a esxproperty; spuštěný bez argumentu vypíše tento seznam. Převodník pro QBCore byl odstraněn v srpnu 2024 a v2.41.0 je poslední vydání, které má convertinventory qb. Přejmenoval amount na count a info na metadata, hotovost z QBCore změnil na item money a zbraním dal sériové číslo a odolnost podle jejich staré hodnoty quality.

Praktické cesty jsou dvě: jednou spustit toto staré vydání na testovacím serveru čistě kvůli převodu a pak ho nahradit aktuálním ox_inventory, nebo stejné mapování polí napsat sám v SQL nebo Lue. V obou případech porovnej před a po několik postav. Po převodu žije hotovost na dvou místech, která ox_inventory udržuje synchronizovaná: v itemu money a v PlayerData.money.cash.

Stashe, kufry a přihrádky

Tady se data ztrácejí nejčastěji. Starší verze qb-inventory je držely v stashitems, trunkitems a gloveboxitems; starý převodník přesunul kufry a přihrádky do player_vehicles, ale se stashi si neporadil. Aktuální qb-inventory (2.x) ukládá všechno do jediné tabulky inventories s klíčem v řetězci identifier, kterou žádný oficiální převodník nečte. V Qboxu ukládá ox_inventory stashe do vlastní tabulky ox_inventory a kufry s přihrádkami do player_vehicles, podle id vozidla.

Rozhodni se tedy, co stojí za zachování. Osobní a pracovní stashe obvykle ano a potřebují malý skript, který přečte každý řádek inventories, itemy převede jako výše a vloží je pod název stashe, který používají definice stashů v ox_inventory. Mnoho serverů usoudí, že obsah kufrů a přihrádek skript nestojí, a oznámí, že budou vyprázdněny. Je to legitimní volba, ale udělej ji vědomě a hráče upozorni před přechodem, ne po něm.

Den přechodu, popořadě#

Jakmile testovací server prošel celým postupem a přežil hru se skutečnými testery, je ostré přepnutí jen kontrolní seznam:

  1. Oznam časové okno údržby a server zavři whitelistem v txAdminu nebo ho zastav.
  2. Udělej poslední mysqldump a záložku souborů serveru v panelu. Obojí si stáhni.
  3. Spusť SQL kroky ve stejném pořadí, které fungovalo na testovacím serveru.
  4. Vyměň resources/ za otestovanou složku a přenes z ní server.cfg, ox.cfg a permissions.cfg.
  5. Nastartuj s otevřenou konzolí. ensure oxmysql, ox_lib, qbx_core a ox_inventory musí naběhnout před čímkoli, co na nich závisí. Na co se v konzoli dívat, popisuje čtení konzole.
  6. Spusť convertjobs a převod inventáře, který sis nacvičil.
  7. Přihlas se za tři postavy, které jsi kontroloval na testovacím serveru. Otevři inventář, stash a kufr.
  8. Otevři server hráčům a první hodinu sleduj konzoli a resmon.

Plán návratu zpět#

Návrat zpět si zapiš dřív, než začneš, protože ve chvíli, kdy ho budeš potřebovat, nebudeš myslet jasně. Migrace je vratná, jen pokud obě poloviny starého serveru stále existují nedotčené.

  • Soubory. Starou složku resources/ a server.cfg ponech jako archiv, nepřepisuj je. Návrat zpět je obnovení té složky.
  • Databáze. Obnov qbcore-before-qbox.sql do databáze. Oprava dopředu není návrat zpět - převedený JSON inventářů, nová collation a player_groups se samy nevrátí.
  • Termín rozhodnutí. Stanov okamžik, od kterého budeš opravovat dopředu místo návratu. Hráči, kteří hráli na Qboxu den, mají data, která by obnova smazala. Rozumné pravidlo: vracej se volně během okna údržby a po něm jen kvůli ztrátě dat.

Na RE:NODE pokrývá záloha v panelu soubory a dump databázi, takže udělej obojí. Zálohu lze zamknout proti rotaci, aby kopie před migrací přežila tvé plánované zálohy, ale obnovu si vyzkoušej na testovacím serveru dřív, než se na ni spolehneš.

Řešení problémů#

Chyby, které se objeví téměř při každé migraci:

PříznakPříčina
qb-inventory is not compatible with qbx_coreqb-inventory je stále spuštěné
contains invalid data při přihlášeníInventář je stále ve formátu QBCore
Chyba cizího klíče při importu qbx_core.sqlCollation sloupců citizenid se liší
Grade práce se zobrazuje jako nilKlíče gradů jsou stále řetězce
Itemy se zobrazují jako prázdné čtverceObrázky nejsou zkopírované
Hráči přišli o prácicleanPlayerGroups zapnuté a práce chybí

Dvě další jsou nenápadnější. Resource, který tiše nedělá nic, obvykle volá QBCore.Shared.Items, aby zjistil, jestli item existuje; tohle vyhledání nahraď voláním exports.ox_inventory:Items(). A duplicitní složky - zapomenuté staré qb-inventory v hranaté složce - spustí tu, kterou FXServer najde první, takže staré smaž, místo abys ho nechával bez ensure.

FAQ#

Můžu provozovat Qbox bez bridge qb-core?

Ano, nastav qbx:enableBridge na false, ale až ve chvíli, kdy na serveru už nic nevolá qb-core. Většina serverů ho nechává zapnutý měsíce a resourcy převádí postupně.

Přijdu při přechodu na Qbox o data postav?

Ne, pokud převedeš správně. Postavy, peníze, metadata, práce a vozidla zůstávají ve stejných tabulkách. Ohrožená data jsou inventáře, stashe, kufry a přihrádky, protože mění formát i tabulky.

Můžu na Qboxu ponechat qb-inventory?

Ne. qbx_core odmítne fungovat, když běží qb-inventory, a ox_inventory je jediný inventář, který Qbox podporuje.

Budou mé placené skripty pro QBCore fungovat na Qboxu?

Mnohé ano přes bridge a mnoho autorů dodává možnost pro Qbox. Rozbijí se ty, které volají qb-inventory nebo qb-target přímo. Přečti si poznámky autora a vyzkoušej to na kopii.

Jak dlouho migrace trvá?

U serveru s menším seznamem resourců je to víkend příprav na testovacím serveru a jedno až dvouhodinové okno údržby. Velké servery s desítkami skriptů závislých na inventáři trvají déle, hlavně kvůli přepisování těchto skriptů.

Můžu se po přechodu vrátit ke QBCore?

Jen obnovením dumpu databáze před migrací a staré složky resources/, což smaže vše, co hráči po přechodu udělali. Termín pro návrat zpět stanov dřív, než začneš.