Ahorra hoy mismo en 20%. Usa el código WELCOME al finalizar la compra. WELCOME

Converting FiveM Scripts – ESX, QBCore, QBOX (Frame…

¿Estás probando un script gratuito?

Los scripts gratuitos son útiles para comprobaciones rápidas. Para servidores de producción, compare los paquetes completos para servidores o los scripts de pago con mantenimiento, teniendo en cuenta el framework y el caso de uso.

Esta es una guía de conversión de scripts de FiveM sencilla, sin tonterías y que prioriza el código, que le muestra exactamente cómo Convertir scripts de FiveM Entre ESX, QBCore, QBOX (qbx_core) y configuraciones independientes de framework. Obtendrá asignaciones de API de tres vías, código de adaptador, pasos de migración de SQL (mysql-async → oxmysql), detalles de QBOX, listas de verificación de pruebas y consejos para el fortalecimiento de la producción.


TL;DR — Migración en 10 pasos

  1. Instantánea y puesta en escena: Realizar copias de seguridad de bases de datos/archivosPonga en marcha un servidor de pruebas local con el marco de destino.
  2. Identificar dependencias: inventory, target, menu/UI, callbacks, DB layer, centro access.
  3. Versiones y orden de los pines: oxmysql → ox_lib → framework (es_extended / qb-core / qbx_core) → sus recursos.
  4. Leer la ruta del código: Encuentra todas las llamadas de jugadores, dinero, trabajos/deberes, inventario, devolución de llamada/evento y base de datos.
  5. API de mapas: Utilice las tablas de Rosetta a continuación para asignar ESX ↔ QBCore ↔ QBOX.
  6. Puentealo: Agregar un puente.lua Adaptador que detecta automáticamente el marco y normaliza las llamadas.
  7. Convertir devoluciones de llamadas: Devoluciones de llamadas ESX/QB → QBOX/ox_lib lib.callback.* cuando sea necesario.
  8. Migrar base de datos: Mover identificadores, cuentas, artículos, vehículos; cambiar a oxmysql *.esperar estilo.
  9. Eventos de endurecimiento: Validar fuente, límites, grupos/trabajos, propiedad; nunca confíe en el cliente.
  10. Control de calidad y lanzamiento: Ejecute las listas de verificación, etiquetas, registros de cambios y planes de reversión.

¿Es usted un desarrollador que busca una solución de adaptador? Consulte nuestro script adaptador gratuito aquí


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

Visión general de la arquitectura

CategoríaESXQBCoreQBOX
Arquitectura / Acceso al núcleoexportaciones['es_extended']:getSharedObject()ESXexportaciones['qb-core']:GetCoreObject()QBCoreNo hay ningún objeto central global; uso exportaciones.qbx_core:* Para jugadores, grupos y notificaciones
Objeto de jugadorESX.GetPlayerFromId(origen)xPlayerQBCore.Functions.GetPlayer(src)Jugadorexportaciones.qbx_core:GetPlayer(src)Jugador con Datos del jugador
IdentificadoresHistóricamente identificador (licencia/steam)ID de ciudadano como clave principalID de ciudadano como clave principal
Dinero ManejoxPlayer.addMoney() / `addAccountMoney('banco''dinero negro')``Player.Functions.AddMoney('efectivo'
Trabajos y deberesxPlayer.job.name, .job.gradeJugador.PlayerData.job.name, .nivel.de.grado, En servicioAyudantes de trabajo/grupo a través de exportaciones.qbx_core:* (controles de grupo, fijadores de tareas)
InventarioESX predeterminado / inventario_de_bueyes / inventario qb (recomendado: inventario_de_bueyes)inventario qb / inventario_de_bueyesinventario_de_bueyes recomendado
Devoluciones de llamadasESX.RegisterServerCallback / ESX.TriggerServerCallbackQBCore.Funciones.CreateCallback / Devolución de llamada del disparadorPreferir biblioteca de buey devoluciones de llamadas (lib.callback.register/await) o exportaciones de QBOX
Capa de base de datosViejo: MySQL asíncrono → Ahora: oxmysql (MySQL.query.await, MySQL.update.await)oxmysqloxmysql
Interfaz de usuario – NotificacionesNotificación ESXNotificar QBQBOX notifica a los ayudantes o lib.notificar
IU – Menúsesx_menu_default / ox_lib:registerContextmenú qb / ox_lib:registerContextox_lib:registerContext / lib.inputDialog
UI – Sistema de destinoobjetivo esx / objetivo_bueyobjetivo qb / objetivo_bueyobjetivo_buey recomendado

¿En qué se diferencia QBOX?

  • Nombre del recurso y exportaciones: núcleo qbx (No Obtener objeto principal).
  • Se apoya en biblioteca de buey (devoluciones de llamadas, notificar) y oxmysql por defecto.
  • Integrados para múltiples caracteres/colas/grupos; ayudantes con opiniones definidas para trabajos/tareas.

Marcos de trabajo FiveM: QBCore frente a ESX

2) Pre-vuelo: Entorno y herramientas

  • Servidor: actual Servidor FX artefactos, Lua 5.4, CFX asegurar orden
  • Orden: garantizar oxmysqlasegurar ox_libgarantizar el marcoasegurar suRecurso
  • Editor: Código VS + Lua LS, aguja; opcional ripgrep para escaneos rápidos de patrones
  • Configuración de prueba: instantánea de base de datos limpia; registro detallado; conjunto de datos pequeños y sembrados
  • Patrones de búsqueda usarás:
    • ESX. xPlayer. QBCore. Datos del jugador núcleo qbx exports.ox_inventory mysql%-async MySQL.

3) Rosetta Stone: ESX ↔ QBCore ↔ QBOX (Mapeo de tres vías)

Copiar y pegar una referencia fácil de usar. Úsala para reemplazar llamadas o conectar tu adaptador.

Núcleo y jugador

ConceptoESXQBCoreQBOX
Obtener el núcleoexportaciones['es_extended']:getSharedObject()exportaciones['qb-core']:GetCoreObject()(n/a — utilizar exportaciones)
Obtener jugador (src)ESX.GetPlayerFromId(origen)QBCore.Functions.GetPlayer(src)exportaciones.qbx_core:GetPlayer(src)
Obtener por citizenid(consulta personalizada)QBCore.Functions.GetPlayerByCitizenId(id)exportaciones.qbx_core:GetPlayerByCitizenId(id) (si está presente)

Identificadores

ConceptoESXQBCoreQBOX
Primarioidentificador (licencia/steam)ID de ciudadanoID de ciudadano
Paso de peatonesmesa id_map(identificador, idciudadano)mismomismo

Dinero

AcciónESXQBCoreQBOX
Añadir efectivoxPlayer.addMoney(a)Jugador.Funciones.AddMoney('efectivo', a)Jugador.PlayerData.money.cash += a (vía adaptador + guardar)
Agregar bancoxPlayer.addAccountMoney('banco', a)Jugador.Funciones.AddMoney('banco', a)Jugador.PlayerData.money.bank += a (adaptador + guardar)
Añadir sucioxPlayer.addAccountMoney('dinero_negro', a)artículo o cuenta adicional (definido por el servidor)Mapa de la billetera de artículos/alternativas (por ejemplo, cripto) (elección del adaptador)

Trabajos, deberes, grupos

ConceptoESXQBCoreQBOX
Leer trabajoxPlayer.job.name, .calificaciónJugador.PlayerData.job.name, .nivel.de.gradoJugador.PlayerData.job.* + ayudantes de grupo
De servicio(varía)Jugador.PlayerData.job.ondutyEstablecer tarea/grupo de ayudantes a través de exportaciones
Comprobación de grupo(Añadir)(Añadir)exportaciones.qbx_core:HasGroup(src, grupo) (ejemplo)

Inventario

AcciónESXQBCoreQBOX
Añadir artículoxPlayer.addInventoryItem(n, c)Jugador.Funciones.AddItem(n, c, ...)preferir inventario_de_bueyes exportar mediante adaptador
inventario_de_bueyesexportaciones.ox_inventario:*exportaciones.ox_inventario:*exportaciones.ox_inventario:*

Devoluciones de llamadas

ConceptoESXQBCoreQBOX
Registro del servidorESX.RegisterServerCallbackQBCore.Funciones.CreateCallbacklib.callback.register (buey_lib)
Desencadenante de clienteESX.TriggerServerCallbackQBCore.Funciones.TriggerCallbacklib.callback.await

Capa de base de datos

ConceptoESX/QB (heredado)oxmysql (objetivo)
BuscarMySQL.Async.fetchAll(sql, parámetros, cb)filas locales = MySQL.query.await(sql, {p1, ...})
ActualizarMySQL.Async.execute(sql, parámetros, cb)aff local = MySQL.update.await(sql, {p1, ...})

UI / Notificar / Objetivo

ConceptoESXQBCoreQBOX
NotificarESX.MostrarNotificación(msg)QBCore.Functions.Notify(msg, tipo)exportaciones.qbx_core:Notificar(...) o lib.notify({...})
Menú(varía)menú qbox_lib:registerContext / entradas
Objetivo(Añadir)objetivo qbobjetivo_buey

Consejo: favor biblioteca de buey, inventario_de_bueyes, objetivo_buey Mantenerse neutral en todos los marcos.


4) Tutorial A: ESX → QBCore (práctico)

Meta: Convierta un recurso de tienda simple de ESX a QBCore.

Paso 1 — Dependencias

  • Asegurar oxmysql, biblioteca de buey, núcleo qb se inician.
  • Si el script utiliza el inventario de ESX, migre a inventario_de_bueyes (recomendado) o asignar al inventario de QB.

Paso 2: Detectar el marco y agregar un puente

Crear puente.lua Para normalizar jugadores/dinero/inventario:

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

Paso 3: Convertir devoluciones de llamadas

  • ESX → QB: reemplazar ESX.RegisterServerCallback con QBCore.Funciones.CreateCallback.
  • Usos del cliente QBCore.Funciones.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('price', price)
  end, 'bread')
else
  local price = lib.callback.await('shop:getPrice', false, 'bread')
  print('price', price)
end

Paso 4: Rutas de dinero e inventario

  • Reemplazar xPlayer.addAccountMoney con Jugador.Funciones.AñadirDinero (para QB) o adaptador.
  • Estandarice todos los cambios de inventario a través del adaptador.

Paso 5: Eventos (seguridad del lado del servidor)

RegisterNetEvent('tienda:comprar', function(item, amount) local src = source si tipo(item) ~= 'string' o tipo(amount) ~= 'number' entonces devuelve fin si amount < 1 o amount > 10 entonces devuelve fin local p = bridge.getPlayer(src) si no p entonces devuelve fin local precio = 100 * amount si no bridge.removeMoney(src, 'cash', price) entonces devuelve fin bridge.addItem(src, item, amount) bridge.notify(src, ('Compró %dx %s'):format(amount, item), 'success') fin)

Paso 6: Migración de la base de datos (identificadores, cuentas)

  • Crear un paso de peatones id_map(identificador, idciudadano).
  • Poblar ID de ciudadano para QB de ESX usuarios tabla mediante regla de elección (columna existente o generada).
-- Ejemplo: crear cruce de caminos y relleno (personalizar según su esquema) CREATE TABLE IF NOT EXISTS id_map ( identifier VARCHAR(64) PRIMARY KEY, citizenid VARCHAR(64) NOT NULL UNIQUE ); -- Suponga que generó nuevos citizenids y los almacenó anteriormente INSERT IGNORE INTO id_map(identifier, citizenid) SELECT u.identifier, u.citizenid FROM users u WHERE u.citizenid IS NOT NULL;

mysql‑async → oxmysql

-- before (mysql-async)
MySQL.Async.fetchAll('SELECT * FROM users WHERE identifier = @id', {['@id'] = identifier}, function(rows) ... end)

-- after (oxmysql)
local rows = MySQL.query.await('SELECT * FROM users WHERE identifier = ?', { identifier })

Paso 7 — Control de calidad

  • Generar artículos, comprar/vender, asegurarse de que los saldos cambien correctamente.
  • Verificar que las devoluciones de llamadas regresen bajo carga.
  • Verifique que se conserven los metadatos del inventario.

5) Tutorial B: QBCore → ESX (práctico)

Advertencias clave:

  • ESX utiliza cuentas para banco/dinero negroEl dinero sucio del mariscal de campo del puerto artículo (si se usa) a la cuenta ESX o guárdelo como un elemento.
  • El esquema de trabajo difiere (grado vs. nivel). Mapéelo cuidadosamente.

Ejemplo: Asignación de dinero mediante adaptador

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

Ejemplo: Conversión de devolución de llamada (servidor)

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

Lista de verificación de pruebas

  • Los trabajos y promociones persisten.
  • Los saldos bancarios/sucios mutan según lo previsto.
  • Validación de propiedad del vehículo y formatos de placas.

6) Tutorial C — QBCore ↔ QBOX (Práctico)

QBCore → QBOX

  • Reemplazar Funciones de QBCore.* con exportaciones.qbx_core:* o biblioteca de buey devoluciones de llamadas.
  • Jugador: QBCore.Functions.GetPlayer(src)exportaciones.qbx_core:GetPlayer(src).
  • Notificar: QBCore.Funciones.Notificarexportaciones.qbx_core:Notificar o lib.notificar.
  • Deber/grupos: utilizar las exportaciones de QBOX (Establecer tarea, HasGroup, etc.).

QBOX → QBCore

  • Reemplazar exportaciones.qbx_core:* con Funciones de QBCore.* equivalentes o su adaptador.
  • Reintroduzca las devoluciones de llamadas QB y los equivalentes de menú/objetivo según sea necesario.

Fragmentos de antes y después

-- Antes de (QB notify) QBCore.Functions.Notify('Hola', 'éxito') -- Después de (QBOX) exports.qbx_core:Notify(source, 'Hola', 'éxito') -- o lib.notify(source, { title = 'Hola', description = 'Bienvenido', type = 'éxito' })
-- Antes de (QB obtener jugador) Jugador local = QBCore.Functions.GetPlayer(src) -- Después de (QBOX) Jugador local = exports.qbx_core:GetPlayer(src)

7) Tutorial D — Framework → Independiente con adaptadores

Escribe tus guiones una vez y ejecutarlos en cualquier lugar:

  • Crear una puente exponiendo una API estable: obtenerJugador, obtenerIdentificador, agregar/quitar dinero, agregar/eliminar elemento, notificar, tieneGrupo, de servicio, devoluciones de llamadas envoltura.
  • Detectar el marco en tiempo de ejecución (núcleo qbxnúcleo qbes_extendidoninguno).
  • Usar biblioteca de buey para devoluciones de llamadas y notificaciones cuando no existe un ayudante de marco directo.

Respaldo independiente mínimo

-- 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) Rendimiento y seguridad (fortalecimiento de la producción)

Validación del lado del servidor (nunca confíes en el cliente)

  • Validar tipos y límites en cada evento.
  • Controlar propiedad, tiempos de reutilización, distancia (si es relevante), trabajo/grupo.
  • Asegúrese de que el dinero no pueda entrar en números negativos; fije las cantidades.
  • Comparar precio del lado del servidor; no acepte totales proporcionados por el cliente.

Estructura del evento

  • Utilice uno evento del servidor por acción; no exponga las funciones de inventario/dinero en bruto a los clientes.
  • Preferir devoluciones de llamadas para flujos de solicitud/respuesta.

Base de datos y rendimiento

  • Cambiar a oxmysql esperar API; escrituras por lotes; evitar consultas por tick.
  • Índice de columnas consultadas con frecuencia (ID de ciudadano, identificador, lámina).
  • Almacenar en caché las listas de precios y configuraciones en la memoria; exportarlas a los clientes una vez y luego compararlas cuando haya cambios.
  • Usar Estado global con moderación; evitar actualizaciones en bucle activo.

9) Errores comunes y manual de depuración

  • Arrogante Obtener objeto principal existe en QBOX → no lo hace; usar exportaciones.qbx_core:*.
  • Las devoluciones de llamadas nunca regresan después de migrar a QBOX → Las devoluciones de llamadas ESX/QB no están registradas; cambiar a lib.callback.register/await.
  • Semántica del dinero sucio diferir → decidir artículo vs cuenta vs billetera alternativa y estandarizar en su adaptador.
  • Supuestos de inventario mixto → normalizar en inventario_de_bueyes.
  • Problemas con la orden de salidaoxmysqlbiblioteca de buey → marco → sus recursos.
  • Desviación de metadatos del vehículo → Asegúrese de que las columnas JSON y los formatos de placa coincidan con el marco de destino.

10) Mejores prácticas de fxmanifest.lua

fx_version 'cerulean' juego 'gta5' lua54 'sí' 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' } -- dependencias (elige lo que uses): ox_lib, oxmysql, ox_inventory, qb-core O qbx_core O es_extended
  • Declarar Lua 5.4 (lua54 'sí').
  • Mantener escrow_ignore mínimo; nunca intente eludir el depósito de garantía.

11) Migración de datos: fragmentos de SQL (ejemplos)

Ajuste los nombres de tablas/columnas a su esquema. Ejecute siempre una copia primero.

Identificadores: ESX → QB/QBOX

-- Agregar citizenid a los usuarios de ESX si faltan ALTER TABLE users ADD COLUMN IF NOT EXISTS citizenid VARCHAR(64); -- Rellenar utilizando un generador determinista o una columna existente UPDATE users SET citizenid = LOWER(SUBSTRING(MD5(CONCAT(identifier,'-QB')),1,10)) WHERE citizenid IS NULL; -- Crear cruce de caminos 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;

Cuentas/Dinero

-- Ejemplo: convertir los saldos bancarios de ESX a la tabla de dinero QB (si su esquema QB lo almacena por separado) 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);

Vehículos

-- Normalizar las placas al formato de destino (ejemplo: 8 caracteres en la parte superior) UPDATE owned_vehicles SET plate = UPPER(LEFT(plate,8)); -- Asegurarse de que las columnas de metadatos JSON sean válidas UPDATE owned_vehicles SET mods = JSON_MERGE_PATCH('{}', mods) WHERE JSON_VALID(mods) = 0;

12) Adaptadores que puedes reutilizar (inicial)

Deje caer esto en puente.lua y se amplía según sus necesidades. Detecta automáticamente ESX/QB/QBOX y expone una API estable.

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) Listas de verificación finales (copiar y enviar)

A) Descubrimiento y prevuelo

  • Instantánea de base de datos/archivos; crear un servidor de prueba
  • Fijar artefactos y versiones de recursos; definir orden de inicio
  • Dependencias de inventario/objetivo/menú enumeradas
  • Decidir la estrategia de identificación (cruce de identificadores ciudadanos)

B) Auditoría de código

  • Grep para ESX/QB/QBOX/ox_*/mysql‑async
  • Enumere todas las llamadas de dinero/inventario/trabajo/obligaciones
  • Lista de devoluciones de llamadas y eventos de servidor/cliente

C) Mapeo y diseño

  • Elija la superficie del adaptador (jugador, identificadores, dinero, elementos, notificaciones, devoluciones de llamadas)
  • Decide una estrategia para el dinero sucio (cuenta vs. artículo vs. billetera alternativa)
  • Favorecer ox_lib/ox_inventory/ox_target

D) Migración de datos

  • Construir un paso de peatones con identificación ciudadana
  • Convertir cuentas/dinero
  • Normalizar metadatos y placas de vehículos
  • Cambiar a llamadas await de oxmysql

E) Pruebas de control de calidad

  • Seguridad de eventos: tipos/límites/propiedad/tiempos de reutilización
  • Devoluciones de llamada: valores de retorno bajo carga
  • Metadatos de inventario conservados
  • La lógica de los trabajos/tareas/grupos coincide con el diseño

F) Liberación y reversión

  • Lanzamiento de etiqueta; registro de cambios
  • Conservar la instantánea previa a la migración durante 7 a 14 días
  • Monitorizar errores/latencia; indexar consultas activas

14) Preguntas frecuentes (con esquema JSON-LD)

P: ¿Puedo portar scripts de QBCore a QBOX sin una reescritura completa?
A: Con adaptadores y biblioteca de buey devoluciones de llamadas, la mayoría de los scripts solo necesitan reasignación de llamadas.

P: ¿Qué hago con el dinero negro/sucio?
A: Estandarizar en su adaptador: ESX → dinero negro Cuenta; QB → artículo o cuenta adicional; QBOX → artículo o billetera alternativa (p. ej., criptomonedas). Mantenga una estrategia para todo el proyecto.

P: ¿Por qué las devoluciones de llamadas se cuelgan después de migrar a QBOX?
A: Las devoluciones de llamadas de ESX/QB no se activarán en QBOX. Usar lib.callback.register/await.

P: ¿Cuál es la mejor manera de migrar MySQL-Async?
A: Reemplazar con oxmysql esperar API; eliminar pirámides de devolución de llamadas.

P: ¿Cómo convierto qb‑target a ox_target?
A: Reemplace las llamadas a la API addBoxZone/Entity una por una; las cargas útiles de los eventos se mantienen similares. Mantenga los nombres de los destinos estables.


15) Visuales (Sugerencias)

  • Diagrama de flujo (Descubrir → Asignar → Adaptar → Migrar base de datos → Probar → Liberar)
  • Diagrama de adaptadores: Script → Puente → Marco de trabajo (ESX/QB/QBOX)
  • Tabla Rosetta: incluido arriba (exportar como CSV para descargas)
[Discover] → [Map APIs] → [Write Adapter] → [Migrate DB] → [Harden] → [QA] → [Release]

  • Respetar licencias (MIT/GPL/NC). No evitar el depósito en garantía o la ofuscación.
  • Convierte únicamente los scripts que propio o tener permiso para adaptarse.

17) Descargables y referencia rápida

También puedes usar este convertidor (aunque no probado):

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


28) Próximos pasos

  • Suelta el puente.lua en su recurso y comience a convertir primero sus scripts de mayor valor.
  • Estandarizar en ox_lib + ox_inventory + ox_target + oxmysql permanecer agnóstico en cuanto al marco.
  • Utilice las listas de verificación durante la revisión y el lanzamiento.

Lea también Migración de SQL e identificadores: Steam/license → citizenid y Cuentas → Money (ESX → QBCore/QBOX)

Lucas
Lucas

Soy Luke, gamer y me encanta escribir sobre FiveM, GTA y juegos de rol. Dirijo una comunidad de juegos de rol y tengo unos 10 años de experiencia administrando servidores.

Artículos: 436