Économisez 20 % avec WELCOMEVoir les promotions
Conversion de scripts FiveM – ESX, QBCore, QBOX (Frame…

Conversion de scripts FiveM – ESX, QBCore, QBOX (Frame…

Il s'agit d'un guide de conversion de scripts FiveM simple et sans fioritures, basé sur le code, qui vous montre exactement comment procéder. Convertir les scripts FiveM entre ESX, QBCore, QBOX (qbx_core) et les configurations indépendantes du framework (autonomes). Vous découvrirez les mappages d'API tridirectionnels, le code de l'adaptateur, les étapes de migration SQL (mysql-async → oxmysql), les spécificités de QBOX, les listes de contrôle des tests et des conseils de renforcement de la production.


TL;DR — Migration en 10 étapes

  1. Instantané et mise en scène : Sauvegarder la base de données/les fichiers. Lancez un serveur de test local avec le framework cible.
  2. Identifier les dépendances : inventaire, cible, menu/interface utilisateur, rappels, couche de base de données, cœur accéder.
  3. Versions et ordre des broches : oxmysql → ox_lib → framework (es_extended / qb-core / qbx_core) → vos ressources.
  4. Lisez le chemin du code : Recherchez tous les joueurs, l'argent, le travail/la tâche, l'inventaire, le rappel/l'événement et les appels DB.
  5. API de carte : Utilisez les tables Rosetta ci-dessous pour mapper ESX ↔ QBCore ↔ QBOX.
  6. Faites le pont : Ajouter un pont.lua adaptateur qui détecte automatiquement le framework et normalise les appels.
  7. Convertir les rappels : Rappels ESX/QB → QBOX/ox_lib lib.callback.* quand c'est nécessaire.
  8. Migrer la base de données : Déplacer les identifiants, les comptes, les articles, les véhicules ; passer à oxmysql *.attendre style.
  9. Durcir les événements : Valider source, limites, groupes/emplois, propriété ; ne faites jamais confiance au client.
  10. QA et publication : Exécutez les listes de contrôle ; balise, journal des modifications et plan de restauration.

Êtes-vous un développeur à la recherche d'une solution d'adaptateur ? Découvrez notre script d'adaptateur gratuit ici


1) Frameworks 101 : ESX vs QBCore vs QBOX vs Standalone

Aperçu architectural

CatégorieESXQB-CoreQBOX
Architecture / Accès au cœurexportations['es_extended']:getSharedObject()ESXexportations['qb-core']:GetCoreObject()QB-CoreAucun objet de base global ; utiliser exportations.qbx_core:* pour les joueurs, les groupes et les notifications
Objet joueurESX.GetPlayerFromId(src)xPlayerQBCore.Functions.GetPlayer(src)Joueurexportations.qbx_core:GetPlayer(src)Joueur avec Données du joueur
IdentifiantsHistoriquement identifiant (licence/vapeur)citoyenid comme clé primairecitoyenid comme clé primaire
Argent ManutentionxPlayer.addMoney() / `addAccountMoney('banque''argent_noir')``Player.Functions.AddMoney('cash'
Emplois et devoirsxPlayer.job.name, .grade.de.travailJoueur.PlayerData.job.name, .niveau.scolaire, En serviceAides à l'emploi/au groupe via exportations.qbx_core:* (contrôles de groupe, responsables des tâches)
InventaireESX par défaut / ox_inventaire / qb-inventaire (recommandé: ox_inventaire)qb-inventaire / ox_inventaireox_inventaire recommandé
RappelsESX.RegisterServerCallback / ESX.TriggerServerCallbackQBCore.Functions.CreateCallback / TriggerCallbackPréférer ox_lib rappels (lib.callback.register/await) ou exportations QBOX
Couche de base de donnéesVieux: mysql-async → Maintenant : oxmysql (MySQL.query.await, MySQL.update.await)oxmysqloxmysql
Interface utilisateur – NotificationsNotification ESXQB NotifyQBOX avertit les assistants ou lib.notify
Interface utilisateur – Menusesx_menu_default / ox_lib:registerContextmenu qb / ox_lib:registerContextox_lib:registerContext / lib.inputDialog
Interface utilisateur – Système cibleesx_target / cible_oxcible qb / cible_oxcible_ox recommandé

En quoi QBOX diffère

  • Nom de la ressource et exportations : qbx_core (Non Obtenir l'objet de base).
  • S'appuie sur ox_lib (rappels, notifier) et oxmysql par défaut.
  • Intégrés pour les personnages multiples/files d'attente/groupes ; aides avisées pour les tâches/tâches.

Cadres FiveM : QBCore vs. ESX

2) Pré-vol : Environnement et outillage

  • Serveur: actuel Serveur FX artefacts, Lua 5.4, CFX assurer commande
  • Commande: assurer oxmysqlassurer ox_libassurer le cadreassurez votre ressource
  • Éditeur: VS Code + Lua LS, stylet; facultatif ripgrep pour des analyses rapides de motifs
  • Configuration de test: instantané de base de données propre ; journalisation détaillée ; petit ensemble de données initialisées
  • Modèles de recherche vous utiliserez :
    • Système de gestion de la sécurité. xPlayer. QBCore. Données du joueur qbx_core exportations.ox_inventory mysql%-async MySQL.

3) Rosetta Stone : ESX ↔ QBCore ↔ QBOX (mappage à trois voies)

Référence conviviale à copier/coller. Utilisez-la pour remplacer des appels ou connecter votre adaptateur.

Noyau et joueur

ConceptESXQB-CoreQBOX
Obtenir le noyauexportations['es_extended']:getSharedObject()exportations['qb-core']:GetCoreObject()(n/a — utiliser les exportations)
Obtenir le joueur (src)ESX.GetPlayerFromId(src)QBCore.Functions.GetPlayer(src)exportations.qbx_core:GetPlayer(src)
Obtenir par citizenid(requête personnalisée)QBCore.Functions.GetPlayerByCitizenId(id)exports.qbx_core:GetPlayerByCitizenId(id) (si présent)

Identifiants

ConceptESXQB-CoreQBOX
Primaireidentifiant (licence/vapeur)citoyenidcitoyenid
Passage cloutétableau id_map(identifiant, citizenid)mêmemême

Argent

ActionESXQB-CoreQBOX
Ajouter de l'argentxPlayer.addMoney(a)Player.Functions.AddMoney('cash', a)Joueur.PlayerData.money.cash += a (via adaptateur + sauvegarde)
Ajouter une banquexPlayer.addAccountMoney('banque', a)Player.Functions.AddMoney('banque', a)Joueur.PlayerData.money.bank += a (adaptateur + sauvegarde)
Ajouter salexPlayer.addAccountMoney('argent_noir', a)élément ou compte supplémentaire (défini par le serveur)mapper vers l'objet/portefeuille alternatif (par exemple, crypto) (choix de l'adaptateur)

Emplois, devoirs, groupes

ConceptESXQB-CoreQBOX
Lire l'offre d'emploixPlayer.job.name, .gradeJoueur.PlayerData.job.name, .niveau.scolaireJoueur.PlayerData.job.* + aides de groupe
De garde(varie)Joueur.PlayerData.job.ondutyDéfinirJobDuty/group helpers via exports
Contrôle de groupe(Ajouter sur)(Ajouter sur)exports.qbx_core:HasGroup(src, groupe) (exemple)

Inventaire

ActionESXQB-CoreQBOX
Ajouter un articlexPlayer.addInventoryItem(n, c)Player.Functions.AddItem(n, c, ...)préférer ox_inventaire exportation via adaptateur
ox_inventaireexportations.ox_inventory:*exportations.ox_inventory:*exportations.ox_inventory:*

Rappels

ConceptESXQB-CoreQBOX
Registre du serveurESX.RegisterServerCallbackQBCore.Functions.CreateCallbacklib.callback.register (ox_lib)
Déclencheur clientESX.TriggerServerCallbackQBCore.Functions.TriggerCallbacklib.callback.await

Couche DB

ConceptESX/QB (hérité)oxmysql (cible)
Aller chercherMySQL.Async.fetchAll(sql, paramètres, cb)lignes locales = MySQL.query.await(sql, {p1, ...})
Mise à jourMySQL.Async.execute(sql, params, cb)local aff = MySQL.update.await(sql, {p1, ...})

Interface utilisateur / Notifier / Cible

ConceptESXQB-CoreQBOX
NotifierESX.ShowNotification(msg)QBCore.Functions.Notify(msg, type)exportations.qbx_core:Notifier(...) ou lib.notify({...})
Menu(varie)menu qbox_lib:registerContext / entrées
Cible(Ajouter sur)cible qbcible_ox

Conseil: service ox_lib, ox_inventaire, cible_ox pour rester neutre dans tous les cadres.


4) Tutoriel A — ESX → QBCore (pratique)

But: Convertissez une ressource de boutique simple d'ESX en QBCore.

Étape 1 — Dépendances

  • Assurer oxmysql, ox_lib, QB-Noyau sont démarrés.
  • Si le script utilise l'inventaire ESX, migrez vers ox_inventaire (recommandé) ou mapper vers l'inventaire QB.

Étape 2 — Détecter le framework et ajouter un pont

Créer pont.lua pour normaliser les joueurs/l'argent/l'inventaire :

-- bridge.lua (ESX/QB/QBOX adapter)
local M = {}
local fw

CreateThread(function()
 if GetResourceState('qbx_core') == 'started' then
 fw = 'qbx'
 elseif GetResourceState('qb-core') == 'started' then
 fw = 'qb'
 elseif GetResourceState('es_extended') == 'started' then
 fw = 'esx'
 else
 fw = 'none'
 end
end)

function M.getFramework()
 return fw
end

function M.getPlayer(src)
 if fw == 'qbx' then
 return exports.qbx_core:GetPlayer(src)
 elseif fw == 'qb' then
 return exports['qb-core']:GetCoreObject().Functions.GetPlayer(src)
 elseif fw == 'esx' then
 return exports['es_extended']:getSharedObject().GetPlayerFromId(src)
 end
end

local function saveQbox(src)
 if fw == 'qbx' and exports.qbx_core and exports.qbx_core.Save then
 exports.qbx_core:Save(src)
 end
end

function M.addMoney(src, account, amount)
 local p = M.getPlayer(src)
 if not p or type(amount) ~= 'number' then return false end
 if fw == 'qb' then
 return p.Functions.AddMoney(account, amount)
 elseif fw == 'esx' then
 if account == 'cash' then
 return p.addMoney(amount)
 elseif account == 'bank' then
 return p.addAccountMoney('bank', amount)
 elseif account == 'black' or account == 'black_money' then
 return p.addAccountMoney('black_money', amount)
 end
 elseif fw == 'qbx' then
 local money = p.PlayerData and p.PlayerData.money or {}
 account = account == 'black' and 'crypto' or account -- example mapping
 money[account] = (money[account] or 0) + amount
 saveQbox(src)
 return true
 end
 return false
end

function M.removeMoney(src, account, amount)
 return M.addMoney(src, account, -math.abs(amount))
end

function M.addItem(src, name, count, meta)
 if GetResourceState('ox_inventory') == 'started' then
 return exports.ox_inventory:AddItem(src, name, count, meta)
 elseif fw == 'qb' then
 return exports['qb-inventory']:AddItem(src, name, count, false, meta)
 elseif fw == 'esx' then
 local p = M.getPlayer(src)
 return p and p.addInventoryItem(name, count)
 elseif fw == 'qbx' then
 return exports.ox_inventory:AddItem(src, name, count, meta)
 end
end

function M.notify(src, msg, ntype)
 if fw == 'qb' then
 TriggerClientEvent('QBCore:Notify', src, msg, ntype or 'primary')
 elseif fw == 'esx' then
 TriggerClientEvent('esx:showNotification', src, msg)
 elseif fw == 'qbx' then
 if exports.qbx_core and exports.qbx_core.Notify then
 exports.qbx_core:Notify(src, msg, ntype or 'info')
 else
 lib.notify(src, { title = 'Notice', description = msg })
 end
 else
 print(('notify(%s): %s'):format(src, msg))
 end
end

return M

Étape 3 — Convertir les rappels

  • ESX → QB : remplacer ESX.RegisterServerCallback avec QBCore.Functions.CreateCallback.
  • Utilisations du client QBCore.Functions.TriggerCallback.
-- server.lua (callback)
local bridge = require 'bridge'

local function getPrice(item)
 return 100
end

if GetResourceState('qb-core') == 'started' then
 local QBCore = exports['qb-core']:GetCoreObject()
 QBCore.Functions.CreateCallback('shop:getPrice', function(source, cb, item)
 cb(getPrice(item))
 end)
else
 -- fallback for QBOX/ESX via ox_lib
 lib.callback.register('shop:getPrice', function(source, item)
 return getPrice(item)
 end)
end
-- client.lua (callback)
if GetResourceState('qb-core') == 'started' then
 local QBCore = exports['qb-core']:GetCoreObject()
 QBCore.Functions.TriggerCallback('shop:getPrice', function(price)
 print('prix', price)
 end, 'bread')
else
 local price = lib.callback.await('shop:getPrice', false, 'bread')
 print('prix', price)
end

Étape 4 — Chemins d'accès à l'argent et aux stocks

  • Remplacer xPlayer.addAccountMoney avec Player.Functions.AddMoney (pour QB) ou adaptateur.
  • Standardisez tous les changements d'inventaire via l'adaptateur.

Étape 5 — Événements (sécurité côté serveur)

RegisterNetEvent('shop:buy', function(item, amount)
 local src = source
 if type(item) ~= 'string' or type(amount) ~= 'number' then return end
 if amount  10 then return end

 local p = bridge.getPlayer(src)
 if not p then return end

 local price = 100 * amount
 if not bridge.removeMoney(src, 'cash', price) then return end
 bridge.addItem(src, item, amount)
 bridge.notify(src, ('Acheté %dx %s'):format(amount, item), 'success')
end)

Étape 6 — Migration de la base de données (identifiants, comptes)

  • Créer un passage piéton id_map(identifiant, citizenid).
  • Peupler citoyenid pour QB d'ESX utilisateurs tableau via règle de choix (colonne existante ou générée).
-- Exemple : créer une table de correspondance et la remplir (personnalisez selon votre schéma)
CREATE TABLE IF NOT EXISTS id_map (
 identifier VARCHAR(64) PRIMARY KEY,
 citizenid VARCHAR(64) NOT NULL UNIQUE
);

-- Supposons que vous ayez généré de nouveaux citizenids et les ayez stockés précédemment
INSERT IGNORE INTO id_map(identifier, citizenid)
SELECT u.identifier, u.citizenid FROM users u WHERE u.citizenid IS NOT NULL;

mysql-async → oxmysql

-- avant (mysql-async) MySQL.Async.fetchAll('SELECT * FROM users WHERE identifier = @id', {['@id'] = identifier}, function(rows) ... end) -- après (oxmysql) local rows = MySQL.query.await('SELECT * FROM users WHERE identifier = ?', { identifier })

Étape 7 — AQ

  • Créez des objets, achetez/vendez, assurez-vous que les soldes changent correctement.
  • Vérifiez que les rappels reviennent sous charge.
  • Vérifiez que les métadonnées d’inventaire sont préservées.

5) Tutoriel B — QBCore → ESX (Pratique)

Principales mises en garde :

  • Utilisations d'ESX comptes pour banque/argent noir. L'argent sale du quart-arrière du port article (si utilisé) sur le compte ESX ou conservez-le en tant qu'élément.
  • Le schéma de poste diffère (grade vs niveau). Cartographiez-le soigneusement.

Exemple : mappage monétaire via un adaptateur

-- in bridge.lua, when fw == 'esx'
function M.qbToEsxMoney(account)
 if account == 'cash' then return 'cash' end
 if account == 'bank' then return 'bank' end
 if account == 'black' or account == 'black_money' then return 'black_money' end
 return account
end

Exemple : Conversion de rappel (serveur)

if GetResourceState('es_extended') == 'started' then
 local ESX = exports['es_extended']:getSharedObject()
 ESX.RegisterServerCallback('garage:getVehicles', function(source, cb)
 local src = source
 local p = bridge.getPlayer(src)
 local rows = MySQL.query.await('SELECT * FROM owned_vehicles WHERE owner = ?', { p.identifier })
 cb(rows)
 end)
end

Liste de contrôle des tests

  • Les offres d'emploi/promotions persistent.
  • Les soldes bancaires/sales mutent comme prévu.
  • Propriété du véhicule et formats de plaques validés.

6) Tutoriel C — QBCore ↔ QBOX (Pratique)

QBCore → QBOX

  • Remplacer QBCore.Functions.* avec exportations.qbx_core:* ou ox_lib rappels.
  • Joueur: QBCore.Functions.GetPlayer(src)exportations.qbx_core:GetPlayer(src).
  • Notifier: QBCore.Fonctions.Notifyexports.qbx_core:Notifier ou lib.notify.
  • Fonction/groupes : utiliser les exportations QBOX (DéfinirJobDuty, HasGroup, etc.).

QBOX → QBCore

  • Remplacer exportations.qbx_core:* avec QBCore.Functions.* équivalents ou votre adaptateur.
  • Réintroduisez les rappels QB et les équivalents de menu/cible si nécessaire.

Extraits avant/après

-- Avant (QB notify) QBCore.Functions.Notify('Bonjour', 'success') -- Après (QBOX) exports.qbx_core:Notify(source, 'Bonjour', 'success') -- ou lib.notify(source, { title = 'Bonjour', description = 'Bienvenue', type = 'success' })
-- Avant (QB get player) local Player = QBCore.Functions.GetPlayer(src) -- Après (QBOX) local Player = exports.qbx_core:GetPlayer(src)

7) Tutoriel D — Framework → Autonome avec adaptateurs

Écrivez vos scripts une fois et les exécuter n'importe où :

  • Créer un pont exposer une API stable : obtenir le joueur, obtenir l'identifiant, ajouter/supprimer de l'argent, ajouter/supprimer un élément, notifier, aGroupe, en service, rappels emballage.
  • Détecter le framework au moment de l'exécution (qbx_coreQB-Noyaues_extendedaucun).
  • Utiliser ox_lib pour les rappels et les notifications lorsqu'aucun assistant de framework direct n'existe.

Solution de secours autonome minimale

-- when fw == 'none'
function M.getPlayer(src)
 -- implement a minimal table or reject actions gracefully
 return { id = src }
end

function M.notify(src, msg)
 print(('notify(%s): %s'):format(src, msg))
end

8) Performances et sécurité (renforcement de la production)

Validation côté serveur (ne jamais faire confiance au client)

  • Valider types et bornes à chaque événement.
  • Vérifier possession, temps de recharge, distance (le cas échéant), emploi/groupe.
  • Assurez-vous que l'argent ne puisse pas devenir négatif ; limitez les montants.
  • Comparer prix côté serveur ; n'acceptez pas les totaux fournis par le client.

Structure de l'événement

  • Utilisez-en un événement serveur par action ; ne pas exposer les fonctions brutes d'inventaire/d'argent aux clients.
  • Préférer rappels pour les flux de requêtes/réponses.

Base de données et performances

  • Passer à oxmysql attendre les API ; écritures par lots ; éviter les requêtes par tick.
  • Indexer les colonnes fréquemment interrogées (citoyenid, identifiant, plaque).
  • Mettre en cache les listes de configuration/prix en mémoire ; les exporter une fois vers les clients, puis les différencier en cas de changement.
  • Utiliser État mondial avec parcimonie ; évitez les mises à jour en boucle à chaud.

9) Pièges courants et manuel de débogage

  • Supposant Obtenir l'objet de base existe sur QBOX → ça ne le fait pas ; utiliser exportations.qbx_core:*.
  • Les rappels ne reviennent jamais après la migration vers QBOX → Les rappels ESX/QB ne sont pas enregistrés ; passez à lib.callback.register/await.
  • Sémantique de l'argent sale différer → décider élément vs compte vs portefeuille alternatif et standardiser dans votre adaptateur.
  • Hypothèses d'inventaire mixtes → normaliser sur ox_inventaire.
  • Problèmes d'ordre de départoxmysqlox_lib → cadre → vos ressources.
  • Dérive des métadonnées du véhicule → s'assurer que les colonnes JSON et les formats de plaque correspondent au framework cible.

10) Meilleures pratiques pour fxmanifest.lua

fx_version 'cerulean'
game 'gta5'

lua54 'yes'

shared_scripts {
 '@ox_lib/init.lua',
 'bridge.lua',
 'config.lua'
}
client_scripts {
 'client/*.lua'
}
server_scripts {
 '@oxmysql/lib/MySQL.lua',
 'server/*.lua'
}

escrow_ignore {
 'bridge.lua', 'config.lua'
}

-- dépendances (choisissez ce que vous utilisez) : ox_lib, oxmysql, ox_inventory, qb-core OU qbx_core OU es_extended
  • Déclarer Lua 5.4 (lua54 'oui').
  • Garder escrow_ignore minimal ; ne tentez jamais de contourner l'entiercement.

11) Migration de données : extraits SQL (exemples)

Ajustez les noms de table/colonne à votre schéma. Exécutez toujours d'abord une copie.

Identifiants : ESX → QB/QBOX

-- Ajouter citizenid aux utilisateurs ESX si manquant
ALTER TABLE users ADD COLUMN IF NOT EXISTS citizenid VARCHAR(64);

-- Remplir avec un générateur déterministe ou une colonne existante
UPDATE users SET citizenid = LOWER(SUBSTRING(MD5(CONCAT(identifier,'-QB')),1,10))
WHERE citizenid IS NULL;

-- Créer une table de correspondance
CREATE TABLE IF NOT EXISTS id_map (
 identifier VARCHAR(64) PRIMARY KEY,
 citizenid VARCHAR(64) NOT NULL UNIQUE
);
INSERT IGNORE INTO id_map(identifier, citizenid)
SELECT identifier, citizenid FROM users WHERE citizenid IS NOT NULL;

Comptes/Argent

-- Exemple : convertir les soldes bancaires ESX en table money QB (si votre schéma QB les stocke séparément)
INSERT INTO player_money (citizenid, account, amount)
SELECT m.citizenid, 'bank', a.money
FROM (
 SELECT u.citizenid, SUM(CASE WHEN account = 'bank' THEN money ELSE 0 END) AS money
 FROM user_accounts ua
 JOIN users u ON u.identifier = ua.identifier
 GROUP BY u.citizenid
) a
JOIN users m ON m.citizenid = a.citizenid
ON DUPLICATE KEY UPDATE amount = VALUES(amount);

Véhicules

-- Normaliser les plaques au format cible (exemple : 8 caractères supérieurs) UPDATE owned_vehicles SET plate = UPPER(LEFT(plate,8)); -- S'assurer que les colonnes de métadonnées JSON sont valides UPDATE owned_vehicles SET mods = JSON_MERGE_PATCH('{}', mods) WHERE JSON_VALID(mods) = 0;

12) Adaptateurs réutilisables (Starter)

Déposez ceci dans pont.lua et s'adapte à vos besoins. Il détecte automatiquement ESX/QB/QBOX et propose une API stable.

local M = {}
local fw = 'none'

CreateThread(function()
 if GetResourceState('qbx_core') == 'started' then fw = 'qbx'
 elseif GetResourceState('qb-core') == 'started' then fw = 'qb'
 elseif GetResourceState('es_extended') == 'started' then fw = 'esx' end
end)

function M.framework() return fw end

function M.player(src)
 if fw == 'qbx' then return exports.qbx_core:GetPlayer(src)
 elseif fw == 'qb' then return exports['qb-core']:GetCoreObject().Functions.GetPlayer(src)
 elseif fw == 'esx' then return exports['es_extended']:getSharedObject().GetPlayerFromId(src) end
end

function M.identifier(src)
 local p = M.player(src); if not p then return nil end
 if fw == 'qb' or fw == 'qbx' then
 return p.PlayerData and p.PlayerData.citizenid
 elseif fw == 'esx' then
 return p.identifier
 end
end

function M.hasGroup(src, group)
 if fw == 'qbx' and exports.qbx_core and exports.qbx_core.HasGroup then
 return exports.qbx_core:HasGroup(src, group)
 end
 return false
end

function M.notify(src, msg, ntype)
 if fw == 'qb' then
 TriggerClientEvent('QBCore:Notify', src, msg, ntype or 'primary')
 elseif fw == 'esx' then
 TriggerClientEvent('esx:showNotification', src, msg)
 elseif fw == 'qbx' then
 if exports.qbx_core and exports.qbx_core.Notify then
 exports.qbx_core:Notify(src, msg, ntype or 'info')
 else
 lib.notify(src, { description = msg })
 end
 end
end

return M

13) Listes de contrôle finales (copie et expédition)

A) Découverte et pré-vol

  • Base de données/fichiers instantanés ; créer un serveur intermédiaire
  • Épingler les artefacts et les versions des ressources ; définir l'ordre de démarrage
  • Dépendances inventaire/cible/menu répertoriées
  • Décider de la stratégie d'identification (passage piéton CitizenID)

B) Audit du code

  • Grep pour ESX/QB/QBOX/ox_*/mysql‑async
  • Énumérez tous les appels d'argent/d'inventaire/de travail/de devoir
  • Lister les rappels et les événements serveur/client

C) Cartographie et conception

  • Choisissez la surface de l'adaptateur (joueur, identifiants, argent, objets, notification, rappels)
  • Décider de la stratégie à adopter pour gérer l'argent sale (compte, objet ou portefeuille alternatif)
  • Privilégiez ox_lib/ox_inventory/ox_target

D) Migration des données

  • Construire un passage piéton Citizenid
  • Convertir des comptes/de l'argent
  • Normaliser les métadonnées et les plaques des véhicules
  • Passer aux appels d'attente oxmysql

E) Tests d'assurance qualité

  • Sécurité des événements : types/limites/propriété/temps de recharge
  • Rappels : valeurs de retour sous charge
  • Métadonnées d'inventaire préservées
  • La logique des tâches/fonctions/groupes correspond à la conception

F) Version et restauration

  • Version de l'étiquette ; journal des modifications
  • Conserver l'instantané de pré-migration pendant 7 à 14 jours
  • Surveiller les erreurs/latences ; indexer les requêtes à chaud

14) FAQ (avec schéma JSON-LD)

Q : Puis-je porter des scripts QBCore vers QBOX sans réécriture complète ?
UN: Avec adaptateurs et ox_lib rappels, la plupart des scripts n'ont besoin que d'appeler le remappage.

Q : Que dois-je faire avec l’argent noir/sale ?
UN: Standardisez dans votre adaptateur : ESX → argent noir compte ; QB → article ou compte supplémentaire ; QBOX → article ou portefeuille alternatif (par exemple, crypto). Gardez une stratégie unique pour l'ensemble du projet.

Q : Pourquoi les rappels se bloquent-ils après le passage à QBOX ?
UN: Les rappels ESX/QB ne se déclenchent pas sur QBOX. Utilisez lib.callback.register/await.

Q : Quelle est la meilleure façon de migrer MySQL-async ?
UN: Remplacer par oxmysql attendre les API ; supprimer les pyramides de rappel.

Q : Comment convertir qb-target en ox_target ?
UN: Remplacez les appels d'API addBoxZone/Entity un par un ; les charges utiles des événements restent similaires. Conservez la stabilité des noms de cible.

{ “@context”: “https://schema.org”, “@type”: “FAQPage”, “mainEntity”: [ { “@type”: “Question”, “name”: “Puis-je porter des scripts QBCore vers QBOX sans réécriture complète ?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Avec des adaptateurs et les callbacks ox_lib, la plupart des scripts nécessitent seulement un remappage des appels.”} }, { “@type”: “Question”, “name”: “Que faire avec l'argent noir/sale ?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Standardisez dans votre adaptateur : ESX → compte black_money ; QB → objet ou compte supplémentaire ; QBOX → objet ou portefeuille alternatif (ex. crypto).”} }, { “@type”: “Question”, “name”: “Pourquoi les callbacks bloquent-ils après le passage à QBOX ?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Les callbacks ESX/QB ne se déclenchent pas sur QBOX. Utilisez lib.callback.register/await.”} }, { “@type”: “Question”, “name”: “Meilleure façon de migrer mysql-async ?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Remplacez par les API await d'oxmysql ; supprimez les pyramides de callbacks.”} }, { “@type”: “Question”, “name”: “Comment convertir qb-target en ox_target ?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Remplacez les appels addBoxZone/Entity API un par un ; les payloads d'événements restent similaires. Gardez les noms de cibles stables.”} } ] }

15) Visuels (Suggestions)

  • Organigramme (Découvrir → Cartographier → Adapter → Migrer la base de données → Tester → Publier)
  • Diagramme des adaptateurs : Script → Pont → Framework (ESX/QB/QBOX)
  • Table de Rosette : inclus ci-dessus (exporter au format CSV pour les téléchargements)
[Découvrir] → [Cartographier les API] → [Écrire l'adaptateur] → [Migrer la base de données] → [Renforcer] → [Assurance qualité] → [Publier]

16) Légal et éthique

  • Respecter les licences (MIT/GPL/NC). Ne pas contourner l'entiercement ou l'obfuscation.
  • Convertissez uniquement les scripts que vous propre ou avoir la permission de s'adapter.

17) Téléchargements et références rapides

Vous pouvez également utiliser ce convertisseur (non testé cependant) :

https://github.com/sledgehamm3r/ESX-QBCore-Converter


28) Prochaines étapes

  • Laissez tomber le pont.lua dans votre ressource et commencez par convertir vos scripts de plus grande valeur.
  • Normaliser sur ox_lib + ox_inventory + ox_target + oxmysql pour rester indépendant du framework.
  • Utilisez les listes de contrôle lors de la révision et de la publication.

Lire aussi Migration SQL et identifiants : Steam/license → citizenid et Comptes → Money (ESX → QBCore/QBOX)