Zwrot callback serwera nil: callbacks ESX, QBCore i ox_lib

ESX.TriggerServerCallback, QBCore TriggerCallback i lib.callback.await zwracają nil? Jak każdy callback działa na serwerze i kliencie, i powody, dla których zwracają nic.

Skrypt klienta pyta serwer o dane, a co wraca to nil, lub nic w ogóle:

text
SCRIPT ERROR: @my_script/client/main.lua:21: attempt to index a nil value (local 'result')

Callbacki serwera to sposób, w jaki klient pyta serwer pytanie i otrzymuje odpowiedź. Każdy framework ma swój, a ox_lib ma jeden, który działa wszędzie. Ten artykuł pokazuje trzy i dlaczego zwracają nil.

ESX

Zarejestruj na serwerze, wyzwól z klienta:

lua
-- server
ESX.RegisterServerCallback('my_script:getMoney', function(source, cb)
    local xPlayer = ESX.GetPlayerFromId(source)
    cb(xPlayer.getMoney())
end)
lua
-- client
ESX.TriggerServerCallback('my_script:getMoney', function(money)
    print(money)
end)

Funkcja serwera otrzymuje source i cb, i przechodzisz odpowiedź do cb. Dodatkowe argumenty z klienta przybyją po cb. Funkcja klienta otrzymuje to co cb wysłał.

QBCore

Nazwy się różnią, kształt jest taki sam:

lua
-- server
local QBCore = exports['qb-core']:GetCoreObject()

QBCore.Functions.CreateCallback('my_script:getMoney', function(source, cb)
    local Player = QBCore.Functions.GetPlayer(source)
    cb(Player.PlayerData.money.cash)
end)
lua
-- client
local QBCore = exports['qb-core']:GetCoreObject()

QBCore.Functions.TriggerCallback('my_script:getMoney', function(money)
    print(money)
end)

Jeśli ESX lub QBCore to nil wewnątrz skryptu, callback nigdy się nie rejestruje. Zobacz ESX is nil i QBCore is nil.

ox_lib

Callbacki ox_lib nie potrzebują frameworku, a odpowiedź to wartość zwrotu zamiast funkcji cb:

lua
-- server
lib.callback.register('my_script:getMoney', function(source)
    local xPlayer = ESX.GetPlayerFromId(source)
    return xPlayer.getMoney()
end)
lua
-- client
local money = lib.callback.await('my_script:getMoney', false)
print(money)

Drugi argument await to opóźnienie w milisekundach między wezwaniem a odpowiedzią (użyj false dla żadnego). Argumenty dla serwera go następują:

lua
local ok = lib.callback.await('my_script:buy', false, 'burger', 2)
lua
lib.callback.register('my_script:buy', function(source, item, amount)
    -- ...
    return true
end)

Aby callback istniał, skrypt ładuje ox_lib w swoim manifeście:

lua
shared_script '@ox_lib/init.lua'

Bez niego, lib to nil: zobacz ox_lib init.lua not found.

Serwer może również wezwać klienta: lib.callback.await('name', playerId, ...) na serwerze, z lib.callback.register na kliencie. Jeśli wolisz brak czekania, lib.callback('name', false, function(result) end) przyjmuje funkcję zamiast.

Dlaczego callback zwraca nil

Prawie każdy przypadek to jeden z nich:

  1. Nazwa się nie zgadza. Nazwy rejestracji i wyzwolenia muszą być identyczne, łącznie z wielkością liter. Literówka nie podnosi błędu, który zauważysz, po prostu nigdy nie odpowiada.
  2. To nie jest zarejestrowane. Plik serwera nigdy nie działał: brakuje go z server_scripts, zasób nie uruchomił się, lub nie powiódł się przed osiągnięciem linii rejestracji.
  3. Błąd na serwerze, przed odpowiedzią. Jeśli funkcja serwera się nie powiedzie, na przykład xPlayer to nil, odpowiedź nigdy nie jest wysłana. Sprawdzaj konsolę serwera, nie klienta.
  4. Nigdy nie wezwiesz cb na każdej ścieżce. Na ESX i QBCore, gałąź, która zwraca bez wezwania cb(...) pozostawia klienta czekającego:
lua
-- wrong: no cb when the player is missing
ESX.RegisterServerCallback('my_script:getJob', function(source, cb)
    local xPlayer = ESX.GetPlayerFromId(source)
    if xPlayer then
        cb(xPlayer.job.name)
    end
end)
lua
-- right
ESX.RegisterServerCallback('my_script:getJob', function(source, cb)
    local xPlayer = ESX.GetPlayerFromId(source)
    cb(xPlayer and xPlayer.job.name or nil)
end)
  1. Zapomnisz return na ox_lib. Funkcja lib.callback.register, która nie ma return odpowiada nil.
  2. Wezwiesz za wcześnie. Callback klienta odpalony przy starcie skryptu może osiągnąć serwer, zanim jego rejestracja działała, po restarcie na przykład. Wyzwól go, gdy gracz się załaduje.
  3. Mieszane style. Callback zarejestrowany z lib.callback.register nie może być wezwany z ESX.TriggerServerCallback. Użyj pasującej pary.

Wskazówka: aby dowiedzieć się, który przypadek masz, dodaj print jako pierwszą linię funkcji serwera. Brak druku oznacza kroki 1 lub 2, druk bez odpowiedzi oznacza 3 do 5.

Ochronę przed nil na kliencie

Traktuj odpowiedź jako coś, co może brakować:

lua
local money = lib.callback.await('my_script:getMoney', false)
if not money then
    return print('No answer from the server')
end

Dla starszych frameworków, sprawdzaj argument przed jego indeksowaniem:

lua
QBCore.Functions.TriggerCallback('my_script:getJob', function(job)
    if not job then return end
    print(job)
end)

Który się используется

  • Pisanie dla jednego frameworku tylko: jego własny callback jest w porządku.
  • Pisanie dla kilka frameworków, lub dla QBox: użyj ox_lib, więc jeden callback działa wszędzie.
  • Pisanie nowego kodu: lib.callback zwraca wartości i czyta się jak zwykła funkcja, co sprawia, że błędy są łatwiejsze do zauważenia.

Jeśli przenosisz skrypt między ESX i QBCore, nazwy callback to jeden wiersz w mapie funkcji.

Lista kontrolna

Symptom Naprawa
Wynik to nil Sprawdzaj, czy nazwa dokładnie się zgadza po obu stronach
Nigdy nie odpowiada Upewnij się, że plik serwera jest w manifeście i zasób uruchomił się
Błąd w konsoli serwera Napraw to; niepowodzenie callback nie wysyła odpowiedzi
ESX lub QBCore: brak odpowiedzi na niektórych ścieżkach Wezwij cb(...) na każdej gałęzi
ox_lib: wynik nil Dodaj return do funkcji lib.callback.register
lib to nil Dodaj shared_script '@ox_lib/init.lua' do manifestu

Szybkie odpowiedzi

Jaka jest różnica między callbackiem a zdarzeniem?

Zdarzenie wysyła wiadomość i nie czeka na odpowiedź. Callback pyta drugą stronę i otrzymuje wartość z powrotem, więc klient może używać dane, które zna tylko serwer.

Czy mogę używać ox_lib callbacks na ESX lub QBCore?

Tak. ox_lib jest niezależny od frameworku, więc lib.callback działa na ESX, QBCore i QBox, o ile ox_lib jest uruchomiony i załadowany przez skrypt.

Dlaczego lib.callback.await zatrzymuje mój skrypt na chwilę?

Czeka na odpowiedź serwera, więc podda wątek. Jeśli serwer nigdy nie odpowiada, ponieważ callback brakuje lub błędy, wątek ciągle czeka lub nie działa z błędem.

Skrypty bez tego problemu

Advanced BoostingBoosting pojazdów z tabletu: kontrakty od klasy D do S+, ekipy i kolejka na żywo.Zobacz skrypt →Quest CreatorWizualny edytor questów i dialogów z NPC, budowanych węzeł po węźle w grze.Zobacz skrypt →Pawn Shop AppLombard między graczami wewnątrz lb-phone.Zobacz skrypt →

Czytaj dalej