Convirtiendo FiveM Scripts – ESX, QBCore, QBOX (Frame...

Convirtiendo FiveM Scripts – ESX, QBCore, QBOX (Marco…

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: inventario, objetivo, menú/UI, callbacks, capa de BD, centro acceso.
  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 *.await estilo.
  9. Eventos de endurecimiento: Validar source, 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úcleoexports['es_extended']:getSharedObject()ESXexports['qb-core']:GetCoreObject()QBCoreNo hay ningún objeto central global; uso exports.qbx_core:* Para jugadores, grupos y notificaciones
Objeto de jugadorESX.GetPlayerFromId(src)xPlayerQBCore.Functions.GetPlayer(src)Playerexports.qbx_core:GetPlayer(src)Player con PlayerData
IdentificadoresHistóricamente identifier (licencia/steam)citizenid como clave principalcitizenid como clave principal
Dinero ManejoxPlayer.addMoney() / `addAccountMoney('banco''dinero negro')``Player.Functions.AddMoney('efectivo'
Trabajos y deberesxPlayer.job.name, .job.gradePlayer.PlayerData.job.name, .grade.level, OnDutyAyudantes de trabajo/grupo a través de exports.qbx_core:* (controles de grupo, fijadores de tareas)
InventarioESX predeterminado / ox_inventory / qb-inventory (recomendado: ox_inventory)qb-inventory / ox_inventoryox_inventory recomendado
Devoluciones de llamadasESX.RegisterServerCallback / ESX.TriggerServerCallbackQBCore.Functions.CreateCallback / TriggerCallbackPreferir ox_lib devoluciones de llamadas (lib.callback.register/await) o exportaciones de QBOX
Capa de base de datosViejo: mysql-async → Ahora: oxmysql (MySQL.query.await, MySQL.update.await)oxmysqloxmysql
Interfaz de usuario – NotificacionesNotificación ESXNotificar QBQBOX notifica a los ayudantes o lib.notify
IU – Menúsesx_menu_default / ox_lib:registerContextqb-menu / ox_lib:registerContextox_lib:registerContext / lib.inputDialog
UI – Sistema de destinoesx_target / ox_targetqb-target / ox_targetox_target recomendado

¿En qué se diferencia QBOX?

  • Nombre del recurso y exportaciones: qbx_core (No GetCoreObject).
  • 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
Convirtiendo scripts FiveM – ESX, QBCore, QBOX (Marco... 3

2) Pre-vuelo: Entorno y herramientas

  • Servidor: actual Servidor FX artefactos, Lua 5.4, CFX ensure pedido
  • Pedido: ensure oxmysqlensure ox_libensure frameworkensure yourResource
  • 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. PlayerData qbx_core 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úcleoexports['es_extended']:getSharedObject()exports['qb-core']:GetCoreObject()(n/a — utilizar exportaciones)
Obtener jugador (src)ESX.GetPlayerFromId(src)QBCore.Functions.GetPlayer(src)exports.qbx_core:GetPlayer(src)
Obtener por citizenid(consulta personalizada)QBCore.Functions.GetPlayerByCitizenId(id)exports.qbx_core:GetPlayerByCitizenId(id) (si está presente)

Identificadores

ConceptoESXQBCoreQBOX
Primarioidentifier (licencia/steam)citizenidcitizenid
Paso de peatonesmesa id_map(identifier, citizenid)mismomismo

Dinero

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

Trabajos, deberes, grupos

ConceptoESXQBCoreQBOX
Leer trabajoxPlayer.job.name, .gradePlayer.PlayerData.job.name, .grade.levelPlayer.PlayerData.job.* + ayudantes de grupo
De servicio(varía)Player.PlayerData.job.ondutySetJobDuty/grupo de ayudantes a través de exportaciones
Comprobación de grupo(Añadir)(Añadir)exports.qbx_core:HasGroup(src, group) (ejemplo)

Inventario

AcciónESXQBCoreQBOX
Añadir artículoxPlayer.addInventoryItem(n, c)Player.Functions.AddItem(n, c, ...)preferir ox_inventory exportar mediante adaptador
inventario_de_bueyesexports.ox_inventory:*exports.ox_inventory:*exports.ox_inventory:*

Devoluciones de llamadas

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

Capa de base de datos

ConceptoESX/QB (heredado)oxmysql (objetivo)
BuscarMySQL.Async.fetchAll(sql, params, cb)local rows = MySQL.query.await(sql, {p1, ...})
ActualizarMySQL.Async.execute(sql, params, cb)local aff = MySQL.update.await(sql, {p1, ...})

UI / Notificar / Objetivo

ConceptoESXQBCoreQBOX
NotificarESX.ShowNotification(msg)QBCore.Functions.Notify(msg, type)exports.qbx_core:Notify(...) o lib.notify({...})
Menú(varía)qb-menuox_lib:registerContext / entradas
Objetivo(Añadir)qb-targetox_target

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, ox_lib, qb-core 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 bridge.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.Functions.CreateCallback.
  • Usos del cliente 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('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 Player.Functions.AddMoney (para QB) o adaptador.
  • Estandarice todos los cambios de inventario a través del adaptador.

Paso 5: Eventos (seguridad del lado del servidor)

RegisterNetEvent('shop:buy', function(item, amount)
 local src = source
 if type(item) ~= 'string' or type(amount) ~= 'number' then return end
 if amount < 1 or 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, ('Bought %dx %s'):format(amount, item), 'success')
end)

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

  • Crear un paso de peatones id_map(identifier, citizenid).
  • Poblar citizenid para QB de ESX users tabla mediante regla de elección (columna existente o generada).
-- Example: create crosswalk and backfill (customize to your schema)
CREATE TABLE IF NOT EXISTS id_map (
 identifier VARCHAR(64) PRIMARY KEY,
 citizenid VARCHAR(64) NOT NULL UNIQUE
);

-- Suppose you generated new citizenids and stored them earlier
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 bank/black_moneyEl 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 QBCore.Functions.* con exports.qbx_core:* o biblioteca de buey devoluciones de llamadas.
  • Jugador: QBCore.Functions.GetPlayer(src)exports.qbx_core:GetPlayer(src).
  • Notificar: QBCore.Functions.Notifyexports.qbx_core:Notify o lib.notify.
  • Deber/grupos: utilizar las exportaciones de QBOX (SetJobDuty, HasGroup, etc.).

QBOX → QBCore

  • Reemplazar exports.qbx_core:* con QBCore.Functions.* 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

-- Before (QB notify)
QBCore.Functions.Notify('Hello', 'success')

-- After (QBOX)
exports.qbx_core:Notify(source, 'Hello', 'success')
-- or
lib.notify(source, { title = 'Hello', description = 'Welcome', type = 'success' })
-- Before (QB get player)
local Player = QBCore.Functions.GetPlayer(src)

-- After (QBOX)
local Player = 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: getPlayer, getIdentifier, add/removeMoney, add/removeItem, notify, hasGroup, onDuty, callbacks envoltura.
  • Detectar el marco en tiempo de ejecución (qbx_coreqb-corees_extendednone).
  • 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 (citizenid, identifier, plate).
  • 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 GlobalState con moderación; evitar actualizaciones en bucle activo.

9) Errores comunes y manual de depuración

  • Arrogante GetCoreObject existe en QBOX → no lo hace; usar exports.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 ox_inventory.
  • Problemas con la orden de salidaoxmysqlox_lib → 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'
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'
}

-- dependencies (pick what you use): ox_lib, oxmysql, ox_inventory, qb-core OR qbx_core OR es_extended
  • Declarar Lua 5.4 (lua54 'yes').
  • 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

-- Add citizenid to ESX users if missing
ALTER TABLE users ADD COLUMN IF NOT EXISTS citizenid VARCHAR(64);

-- Populate using a deterministic generator or an existing column
UPDATE users SET citizenid = LOWER(SUBSTRING(MD5(CONCAT(identifier,'-QB')),1,10))
WHERE citizenid IS NULL;

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

-- Example: convert ESX bank balances to QB money table (if your QB schema stores it separately)
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

-- Normalize plates to target format (example: 8 chars upper)
UPDATE owned_vehicles SET plate = UPPER(LEFT(plate,8));

-- Ensure JSON metadata columns are valid
UPDATE owned_vehicles SET mods = JSON_MERGE_PATCH('{}', mods) WHERE JSON_VALID(mods) = 0;

12) Adaptadores que puedes reutilizar (inicial)

Deje caer esto en bridge.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 → black_money 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.

{ “@context”: “https://schema.org”, “@type”: “FAQPage”, “mainEntity”: [ { “@type”: “Question”, “name”: “¿Puedo portar QBCore scripts a QBOX sin una reescritura completa?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Con adaptadores y callbacks de ox_lib, la mayoría de los scripts solo necesitan remapeo.”} }, { “@type”: “Question”, “name”: “¿Qué hago con el dinero negro/sucio?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Estandariza en tu adaptador: ESX → cuenta de black_money; QB → elemento o cuenta extra; QBOX → elemento o billetera alternativa (ej. cripto).”} }, { “@type”: “Question”, “name”: “¿Por qué los callbacks se quedan colgados después de moverse a QBOX?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Los callbacks de ESX/QB no se dispararán en QBOX. Usa lib.callback.register/await.”} }, { “@type”: “Question”, “name”: “¿Mejor manera de migrar mysql-async?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Reemplaza con APIs de espera de oxmysql; elimina pirámides de callbacks.”} }, { “@type”: “Question”, “name”: “¿Cómo convierto qb-target a ox_target?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Reemplaza las llamadas de API addBoxZone/Entity una por una; las cargas de eventos permanecen similares. Mantén los nombres de destino 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]

16) Legal y ético

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