Konvertiere ein ESX-Skript zu QBCore (und zurück): Funktionskarte und Bridge
Portiere ein FiveM-Skript zwischen ESX und QBCore: eine Tabelle der häufigen Aufrufe (Spieler, Geld, Job, Gegenstände, Benachrichtigungen, Callbacks) und eine Bridge-Datei, die beide unterstützt.
Du hast ein Skript für ESX geschrieben, und dein Server läuft QBCore, oder umgekehrt. Das meiste des Skripts ist einfach Lua und natives, das sich nicht ändert. Nur die Framework-Aufrufe tun es, und es gibt weniger davon als du denkst. Dieser Artikel gibt dir eine Karte davon, und zeigt dir dann, wie man sie in einer Bridge-Datei isoliert.
Was bleibt und was ändert sich
Native, NUI, deine eigenen Events, Schleifen, Ziele und Menüs funktionieren auf jedem Framework. Was sich ändert ist eine kurze Liste:
- wie du das Framework-Objekt bekommst
- wie du einen Spieler bekommst
- Geld, Jobs und Gegenstände
- Benachrichtigungen
- usbare Gegenstände und Callbacks
- die Datenbanktabellen für Spieler
Suche das Skript nach ESX. und xPlayer und jeder Hit ist etwas zu konvertieren.
Funktionskarte
| Aufgabe | ESX Legacy | QBCore |
|---|---|---|
| Besorge das Objekt | ESX = exports['es_extended']:getSharedObject() |
local QBCore = exports['qb-core']:GetCoreObject() |
| Besorge einen Spieler (Server) | ESX.GetPlayerFromId(src) |
QBCore.Functions.GetPlayer(src) |
| Spieler-Identifier | xPlayer.identifier |
Player.PlayerData.citizenid |
| Bargeldbestand | xPlayer.getMoney() |
Player.PlayerData.money.cash |
| Geld hinzufügen | xPlayer.addMoney(n) |
Player.Functions.AddMoney('cash', n) |
| Geld entfernen | xPlayer.removeMoney(n) |
Player.Functions.RemoveMoney('cash', n) |
| Bank hinzufügen | xPlayer.addAccountMoney('bank', n) |
Player.Functions.AddMoney('bank', n) |
| Bank entfernen | xPlayer.removeAccountMoney('bank', n) |
Player.Functions.RemoveMoney('bank', n) |
| Jobname | xPlayer.job.name |
Player.PlayerData.job.name |
| Job-Grad | xPlayer.job.grade |
Player.PlayerData.job.grade.level |
| Gegenstand hinzufügen | xPlayer.addInventoryItem(name, n) |
Player.Functions.AddItem(name, n) |
| Gegenstand entfernen | xPlayer.removeInventoryItem(name, n) |
Player.Functions.RemoveItem(name, n) |
| Gegenstands-Anzahl | xPlayer.getInventoryItem(name).count |
Player.Functions.GetItemByName(name) (nil wenn keine, dann .amount) |
| Usbar-Gegenstand | ESX.RegisterUsableItem(name, function(src) end) |
QBCore.Functions.CreateUseableItem(name, function(src, item) end) |
| Benachrichtigung (Client) | ESX.ShowNotification(msg) |
QBCore.Functions.Notify(msg, 'success') |
| Benachrichtigung (Server) | xPlayer.showNotification(msg) |
TriggerClientEvent('QBCore:Notify', src, msg, 'success') |
| Spieler-Daten (Client) | ESX.GetPlayerData() |
QBCore.Functions.GetPlayerData() |
| Spieler-geladen-Event | esx:playerLoaded |
QBCore:Client:OnPlayerLoaded |
| Job-geändert-Event | esx:setJob |
QBCore:Client:OnJobUpdate |
| Server-Callback | ESX.RegisterServerCallback |
QBCore.Functions.CreateCallback |
Zwei Details verwirren Menschen. Geldtypen: ESX hat money für Bargeld und bank, QBCore verwendet 'cash' und 'bank' als das erste Argument. Und der Grad: ESX gibt eine einfache Zahl, QBCore eine Tabelle, also job.grade.level.
Callbacks, die jedes zweite Skript verwendet, werden detailliert verglichen in Server-Callbacks auf ESX, QBCore und ox_lib.
Die Datenbank
Die Spieler-Tabellen unterscheiden sich, daher braucht jede SELECT oder UPDATE auf ihnen eine Änderung:
| ESX | QBCore | |
|---|---|---|
| Spieler | users |
players |
| Spieler-Schlüssel | identifier (ein license:-String) |
citizenid |
| Fahrzeuge | owned_vehicles |
player_vehicles |
Ein Skript, das seine eigenen Daten speichert, mit seinen eigenen Tabellen, funktioniert normalerweise weiterhin, solange es die Zeilen mit einem Wert schlüsselt, den du von jedem Framework bekommen kannst. Den License-Identifier dafür zu verwenden funktioniert auf beiden.
QBox
QBox ist näher an QBCore als an ESX. Sein Kern ist qbx_core, es behält eine Kompatibilitätsschicht für exports['qb-core']:GetCoreObject() und sein Inventar ist ox_inventory. Ein Skript, das zu QBCore konvertiert wurde, läuft normalerweise auf QBox mit wenigen Änderungen, abgesehen von Inventar-Aufrufen.
Der Bridge-Datei-Ansatz
Wenn das Skript auf beiden laufen muss, verteile es nicht mit if ESX then ... else ... end. Lege jeden Framework-Aufruf in eine Datei und lasse den Rest des Skripts diese Datei aufrufen.
-- 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
endIm Manifest lade es vor den Dateien, die es verwenden:
server_scripts {
'bridge.lua',
'server.lua',
}Das Skript liest sich dann so und erwähnt nie ein Framework:
RegisterNetEvent('my_script:pay', function()
local src = source
local job = Bridge.GetJob(src)
if job == 'mechanic' then
Bridge.AddCash(src, 100)
end
end)Füge eine Client-Bridge für Benachrichtigungen und Spieler-Daten auf die gleiche Weise hinzu. Wenn du ein neues Framework hinzufügst, wie QBox mit qbx_core, fügst du einen Zweig in der Bridge hinzu, und das Skript bleibt wie es ist.
Denk daran, dass eine Bridge nur funktioniert, wenn das Framework zuerst startet. Lege ensure es_extended oder ensure qb-core über dem Skript in server.cfg ein und lese ESX ist nil, falls das Objekt nil zurückkommt.
Checkliste
| Symptom | Behebung |
|---|---|
attempt to index a nil value (global 'ESX') bei QBCore |
Ein ESX-Aufruf bleibt; ersetze ihn aus der obigen Karte |
| Geld oder Job immer nil | Du liest PlayerData auf ESX oder xPlayer.job auf QBCore |
| Gegenstands-Anzahl-Fehler auf QBCore | GetItemByName gibt nil zurück, wenn der Spieler keine hat; überprüfe es zuerst |
| Falsche Tabelle in einer Abfrage | users und identifier auf ESX, players und citizenid auf QBCore |
| Callback gibt nichts zurück | Verwende die passenden Register- und Trigger-Aufrufe für das Framework |
| Braucht beide Frameworks | Verschiebe jeden Framework-Aufruf in eine Bridge-Datei |
Kurze Antworten
Kann ich jedes ESX-Skript zu QBCore konvertieren?
Skripte, die das Framework nur für Spieler, Geld, Jobs, Gegenstände und Benachrichtigungen verwenden, konvertieren sich gut. Skripte, die um Framework-spezifische Ressourcen wie esx_society oder qb-management herum gebaut sind, müssen auch diese Teile umgeschrieben werden.
Ändert sich die Datenbank, wenn ich Framework wechsle?
Ja. ESX speichert Spieler in users mit einem identifier, und QBCore in players mit einer citizenid. Abfragen und Tabellennamen im Skript müssen dem Framework folgen, das du laufen lässt.
Ist eine Bridge-Datei besser als Konvertierung?
Wenn du das Skript auf beiden Frameworks brauchst, ja: Du änderst eine Datei, nicht das ganze Skript. Wenn du nur ein Framework laufen lässt, konvertiere einmal und verwerfe den anderen Zweig.
Scripts ohne dieses Problem
Item Creator V2Erstelle nutzbare Items mit Animationen, Props, Effekten und mehr — ganz ohne Code.Script ansehen →
Shop CreatorBau einen Shop in unter einer Minute — Besitzer, Angestellte, Tresore und Überfälle inklusive.Script ansehen →
Advanced BoostingFahrzeug-Boosting per Tablet: Aufträge von Klasse D bis S+, Crews und eine Live-Warteschlange.Script ansehen →