Converti uno script ESX a QBCore (e viceversa): mappa delle funzioni e bridge
Porta uno script FiveM tra ESX e QBCore: una tabella delle chiamate comuni (giocatore, soldi, lavoro, articoli, notifiche, callback) e un file bridge che supporta entrambi.
Hai uno script scritto per ESX, e il tuo server esegue QBCore, o viceversa. La maggior parte dello script è Lua semplice e nativi che non cambiano. Solo le chiamate del framework cambiano, e ce ne sono meno di quello che ti aspetti. Questo articolo ti fornisce una mappa di esse, e poi mostra come isolarle in un file bridge.
Cosa rimane e cosa cambia
Nativi, NUI, i tuoi eventi, loop, target e menu funzionano su qualsiasi framework. Quello che cambia è una breve lista:
- come ottenere l'oggetto del framework
- come ottenere un giocatore
- soldi, lavori e articoli
- notifiche
- articoli usabili e callback
- le tabelle di database per i giocatori
Cerca nel script ESX. e xPlayer, e ogni hit è qualcosa da convertire.
Mappa delle funzioni
| Attività | ESX Legacy | QBCore |
|---|---|---|
| Ottieni l'oggetto | ESX = exports['es_extended']:getSharedObject() |
local QBCore = exports['qb-core']:GetCoreObject() |
| Ottieni un giocatore (server) | ESX.GetPlayerFromId(src) |
QBCore.Functions.GetPlayer(src) |
| Identificatore del giocatore | xPlayer.identifier |
Player.PlayerData.citizenid |
| Saldo contanti | xPlayer.getMoney() |
Player.PlayerData.money.cash |
| Aggiungi contanti | xPlayer.addMoney(n) |
Player.Functions.AddMoney('cash', n) |
| Rimuovi contanti | xPlayer.removeMoney(n) |
Player.Functions.RemoveMoney('cash', n) |
| Aggiungi banca | xPlayer.addAccountMoney('bank', n) |
Player.Functions.AddMoney('bank', n) |
| Rimuovi banca | xPlayer.removeAccountMoney('bank', n) |
Player.Functions.RemoveMoney('bank', n) |
| Nome lavoro | xPlayer.job.name |
Player.PlayerData.job.name |
| Grado lavoro | xPlayer.job.grade |
Player.PlayerData.job.grade.level |
| Aggiungi articolo | xPlayer.addInventoryItem(name, n) |
Player.Functions.AddItem(name, n) |
| Rimuovi articolo | xPlayer.removeInventoryItem(name, n) |
Player.Functions.RemoveItem(name, n) |
| Conteggio articoli | xPlayer.getInventoryItem(name).count |
Player.Functions.GetItemByName(name) (nil se nessuno, poi .amount) |
| Articolo usabile | ESX.RegisterUsableItem(name, function(src) end) |
QBCore.Functions.CreateUseableItem(name, function(src, item) end) |
| Notifica (client) | ESX.ShowNotification(msg) |
QBCore.Functions.Notify(msg, 'success') |
| Notifica (server) | xPlayer.showNotification(msg) |
TriggerClientEvent('QBCore:Notify', src, msg, 'success') |
| Dati del giocatore (client) | ESX.GetPlayerData() |
QBCore.Functions.GetPlayerData() |
| Evento di caricamento del giocatore | esx:playerLoaded |
QBCore:Client:OnPlayerLoaded |
| Evento cambio lavoro | esx:setJob |
QBCore:Client:OnJobUpdate |
| Callback del server | ESX.RegisterServerCallback |
QBCore.Functions.CreateCallback |
Due dettagli confondono le persone. Tipi di soldi: ESX ha money per contanti e bank, QBCore usa 'cash' e 'bank' come primo argomento. E il grado: ESX fornisce un numero semplice, QBCore una tabella, quindi job.grade.level.
I callback, che ogni secondo script usa, vengono confrontati in dettaglio in server callbacks on ESX, QBCore and ox_lib.
Il database
Le tabelle dei giocatori differiscono, quindi qualsiasi SELECT o UPDATE su di esse ha bisogno di un cambiamento:
| ESX | QBCore | |
|---|---|---|
| Giocatori | users |
players |
| Chiave del giocatore | identifier (una stringa license:) |
citizenid |
| Veicoli | owned_vehicles |
player_vehicles |
Uno script che memorizza i suoi dati, con le sue proprie tabelle, di solito continua a funzionare, finché chiavi le righe su un valore che puoi ottenere da qualsiasi framework. Usare l'identificatore della licenza per quello funziona su entrambi.
QBox
QBox è più vicino a QBCore che a ESX. Il suo core è qbx_core, mantiene un livello di compatibilità per exports['qb-core']:GetCoreObject(), e il suo inventario è ox_inventory. Uno script convertito a QBCore di solito viene eseguito su QBox con pochi cambiamenti, a parte le chiamate di inventario.
L'approccio del file bridge
Se lo script deve essere eseguito su entrambi, non infarcirlo di if ESX then ... else ... end. Metti ogni chiamata del framework in un file, e fai che il resto dello script chiami quel file.
-- bridge.lua (server)
Bridge = {}
local framework
if GetResourceState('es_extended') == 'started' then
framework = 'esx'
ESX = exports['es_extended']:getSharedObject()
elseif GetResourceState('qb-core') == 'started' then
framework = 'qb'
QBCore = exports['qb-core']:GetCoreObject()
end
function Bridge.GetPlayer(src)
if framework == 'esx' then return ESX.GetPlayerFromId(src) end
return QBCore.Functions.GetPlayer(src)
end
function Bridge.AddCash(src, amount)
local player = Bridge.GetPlayer(src)
if not player then return false end
if framework == 'esx' then
player.addMoney(amount)
else
player.Functions.AddMoney('cash', amount)
end
return true
end
function Bridge.GetJob(src)
local player = Bridge.GetPlayer(src)
if not player then return nil end
if framework == 'esx' then
return player.job.name, player.job.grade
end
return player.PlayerData.job.name, player.PlayerData.job.grade.level
endNel manifest, caricalo prima dei file che lo usano:
server_scripts {
'bridge.lua',
'server.lua',
}Lo script legge così, e non menziona mai un framework:
RegisterNetEvent('my_script:pay', function()
local src = source
local job = Bridge.GetJob(src)
if job == 'mechanic' then
Bridge.AddCash(src, 100)
end
end)Aggiungi un client bridge per notifiche e dati di giocatore nello stesso modo. Quando aggiungi un nuovo framework, come QBox con qbx_core, aggiungi un ramo nel bridge, e lo script rimane come è.
Ricorda che un bridge funziona solo se il framework si avvia per primo. Metti ensure es_extended o ensure qb-core sopra lo script in server.cfg, e leggi ESX is nil se l'oggetto torna nil.
Checklist
| Sintomo | Soluzione |
|---|---|
attempt to index a nil value (global 'ESX') su QBCore |
Una chiamata ESX è rimasta; sostituiscila dalla mappa sopra |
| Soldi o lavoro sempre nil | Leggi PlayerData su ESX, o xPlayer.job su QBCore |
| Errori di conteggio articoli su QBCore | GetItemByName restituisce nil quando il giocatore non ne ha; controllalo prima |
| Tabella sbagliata in una query | users e identifier su ESX, players e citizenid su QBCore |
| Callback non restituisce nulla | Usa le corrispondenti chiamate di register e trigger per il framework |
| Ha bisogno di entrambi i framework | Sposta ogni chiamata del framework in un file bridge |
Risposte rapide
Posso convertire qualsiasi script ESX a QBCore?
Gli script che usano solo il framework per giocatori, soldi, lavori, articoli e notifiche si convertono bene. Gli script costruiti attorno a risorse specifiche del framework, come esx_society o qb-management, hanno bisogno che anche quelle parti vengano riscritte.
Il database cambia quando passo da un framework all'altro?
Sì. ESX memorizza i giocatori in users con un identifier, e QBCore in players con un citizenid. Le query e i nomi delle tabelle nello script devono seguire il framework che esegui.
Un file bridge è meglio che convertire?
Se hai bisogno dello script su entrambi i framework, sì: modifichi un file, non l'intero script. Se esegui solo un framework, converti una volta e abbandona l'altro ramo.
Script senza questo problema
Item Creator V2Crea oggetti utilizzabili con animazioni, props, effetti e altro — senza scrivere codice.Vedi script →
Shop CreatorCrea un negozio in meno di un minuto — proprietari, dipendenti, casseforti e rapine inclusi.Vedi script →
Advanced BoostingBoosting di veicoli dal tablet: contratti dalla classe D alla S+, crew e coda in tempo reale.Vedi script →