Konwertuj skrypt ESX na QBCore (i odwrotnie): mapa funkcji i most
Portuj skrypt FiveM między ESX i QBCore: tabelę wspólnych wołań (gracz, pieniądze, praca, przedmioty, powiadomienia, callbacki) i plik mostu, który wspiera oba.
Masz skrypt napisany dla ESX i twój serwer uruchamia QBCore, lub odwrotnie. Większość skryptu to zwykły Lua i natives, które się nie zmieniają. Tylko wołania struktury robią, i są mniej niż się spodziewasz. Ten artykuł daje ci mapę, potem pokazuje jak izolować je w jednym pliku mostu.
Co zostaje i co się zmienia
Natives, NUI, twoje własne zdarzenia, pętle, cele i menu działają na każdej strukturze. Co się zmienia, to krótka lista:
- jak otrzymujesz obiekt struktury
- jak otrzymujesz gracza
- pieniądze, prace i przedmioty
- powiadomienia
- przedmioty użyteczne i callbacki
- tabele bazy danych dla graczy
Wyszukaj w skrypcie ESX. i xPlayer, i każde trafienie to coś do konwersji.
Mapa funkcji
| Zadanie | ESX Legacy | QBCore |
|---|---|---|
| Pozyskaj obiekt | ESX = exports['es_extended']:getSharedObject() |
local QBCore = exports['qb-core']:GetCoreObject() |
| Pozyskaj gracza (serwer) | ESX.GetPlayerFromId(src) |
QBCore.Functions.GetPlayer(src) |
| Identyfikator gracza | xPlayer.identifier |
Player.PlayerData.citizenid |
| Saldo gotówki | xPlayer.getMoney() |
Player.PlayerData.money.cash |
| Dodaj gotówkę | xPlayer.addMoney(n) |
Player.Functions.AddMoney('cash', n) |
| Usuń gotówkę | xPlayer.removeMoney(n) |
Player.Functions.RemoveMoney('cash', n) |
| Dodaj bank | xPlayer.addAccountMoney('bank', n) |
Player.Functions.AddMoney('bank', n) |
| Usuń bank | xPlayer.removeAccountMoney('bank', n) |
Player.Functions.RemoveMoney('bank', n) |
| Nazwa pracy | xPlayer.job.name |
Player.PlayerData.job.name |
| Stopień pracy | xPlayer.job.grade |
Player.PlayerData.job.grade.level |
| Dodaj przedmiot | xPlayer.addInventoryItem(name, n) |
Player.Functions.AddItem(name, n) |
| Usuń przedmiot | xPlayer.removeInventoryItem(name, n) |
Player.Functions.RemoveItem(name, n) |
| Liczba przedmiotów | xPlayer.getInventoryItem(name).count |
Player.Functions.GetItemByName(name) (nil jeśli żaden, potem .amount) |
| Przedmiot użyteczny | ESX.RegisterUsableItem(name, function(src) end) |
QBCore.Functions.CreateUseableItem(name, function(src, item) end) |
| Powiadom (klient) | ESX.ShowNotification(msg) |
QBCore.Functions.Notify(msg, 'success') |
| Powiadom (serwer) | xPlayer.showNotification(msg) |
TriggerClientEvent('QBCore:Notify', src, msg, 'success') |
| Dane gracza (klient) | ESX.GetPlayerData() |
QBCore.Functions.GetPlayerData() |
| Zdarzenie załadowania gracza | esx:playerLoaded |
QBCore:Client:OnPlayerLoaded |
| Zdarzenie zmiany pracy | esx:setJob |
QBCore:Client:OnJobUpdate |
| Callback serwera | ESX.RegisterServerCallback |
QBCore.Functions.CreateCallback |
Dwa szczegóły tripują ludzi. Typy pieniędzy: ESX ma money dla gotówki i bank, QBCore używa 'cash' i 'bank' jako pierwszy argument. I stopień: ESX daje zwykłą liczbę, QBCore tabelę, więc job.grade.level.
Callbacki, które każdy drugi skrypt używa, są porównywane szczegółowo w server callbacks on ESX, QBCore and ox_lib.
Baza danych
Tabele graczy się różnią, więc każde SELECT lub UPDATE na nich potrzebuje zmianę:
| ESX | QBCore | |
|---|---|---|
| Gracze | users |
players |
| Klucz gracza | identifier (ciąg license:) |
citizenid |
| Pojazdy | owned_vehicles |
player_vehicles |
Skrypt, który przechowuje swoje własne dane, z własnymi tabelami, zwykle ciągle działa, dopóki kluczuje wiersze na wartości, którą możesz uzyskać z każdej struktury. Używanie identyfikatora licencji do tego działa na obu.
QBox
QBox jest bliżej do QBCore niż do ESX. Jego rdzeń to qbx_core, przechowuje warstwę kompatybilności dla exports['qb-core']:GetCoreObject(), i jego inwentarz to ox_inventory. Skrypt konwertowany na QBCore zwykle działa na QBox z kilkoma zmianami, oprócz wołań inwentarza.
Podejście pliku mostu
Jeśli skrypt musi działać na obu, nie zaśmiecaj go z if ESX then ... else ... end. Włóż każde wołanie struktury w jeden plik i miej resztę skryptu wołającą ten plik.
-- 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
endW manifeście, załaduj to przed plikami, które go używają:
server_scripts {
'bridge.lua',
'server.lua',
}Skrypt następnie czyta tak, i nigdy nie wspomina struktury:
RegisterNetEvent('my_script:pay', function()
local src = source
local job = Bridge.GetJob(src)
if job == 'mechanic' then
Bridge.AddCash(src, 100)
end
end)Dodaj most klienta dla powiadomień i danych gracza w ten sam sposób. Gdy dodasz nową strukturę, taką jak QBox z qbx_core, dodajesz gałąź w moście, i skrypt zostaje takim, jaki jest.
Pamiętaj, że most działa tylko jeśli struktura się uruchamia pierwsza. Włóż ensure es_extended lub ensure qb-core ponad skrypt w server.cfg, i przeczytaj ESX is nil, jeśli obiekt wraca nil.
Lista kontrolna
| Symptom | Naprawa |
|---|---|
attempt to index a nil value (global 'ESX') na QBCore |
Wołanie ESX pozostało; zamień je z mapy powyżej |
| Pieniądze lub praca zawsze nil | Czytasz PlayerData na ESX, lub xPlayer.job na QBCore |
| Błędy liczby przedmiotów na QBCore | GetItemByName wraca nil, gdy gracz nie ma żadnego; sprawdź to najpierw |
| Zła tabela w zapytaniu | users i identifier na ESX, players i citizenid na QBCore |
| Callback nic nie zwraca | Użyj dopasowanego rejestru i wyzwolenia wołań dla struktury |
| Potrzebuje obu struktur | Przenieś każde wołanie struktury do pliku mostu |
Szybkie odpowiedzi
Czy mogę konwertować każdy skrypt ESX na QBCore?
Skrypty, które używają struktury tylko dla graczy, pieniędzy, prac, przedmiotów i powiadomień konwertują się dobrze. Skrypty zbudowane wokół zasobów specyficznych dla struktury, takie jak esx_society lub qb-management, potrzebują też tych części przepisane.
Czy baza danych się zmienia, gdy przełączam strukturę?
Tak. ESX przechowuje graczy w users z identifier, a QBCore w players z citizenid. Zapytania i nazwy tabel w skrypcie muszą postępować zgodnie ze strukturą, którą uruchamiasz.
Czy plik mostu jest lepszy niż konwertowanie?
Jeśli potrzebujesz skryptu na obu strukturach, tak: zmieniasz jeden plik, nie cały skrypt. Jeśli uruchamiasz tylko jedną strukturę, konwertuj raz i porzuć inną gałąź.
Skrypty bez tego problemu
Item Creator V2Twórz używalne przedmioty z animacjami, propami, efektami i nie tylko — bez pisania kodu.Zobacz skrypt →
Shop CreatorZbuduj sklep w niecałą minutę — właściciele, pracownicy, sejfy i napady w zestawie.Zobacz skrypt →
Advanced BoostingBoosting pojazdów z tabletu: kontrakty od klasy D do S+, ekipy i kolejka na żywo.Zobacz skrypt →