La callback del server ritorna nil: ESX, QBCore e callback ox_lib

ESX.TriggerServerCallback, QBCore TriggerCallback e lib.callback.await ritorna nil? Come ogni callback funziona sul server e client, e le ragioni per cui ritornano nulla.

Uno script client chiede al server dati, e quello che torna è nil, o nulla affatto:

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

Le callback del server sono come il client chiede al server una domanda e ottiene una risposta. Ogni framework ha la sua, e ox_lib ha una che funziona ovunque. Questo articolo mostra i tre e perché ritornano nil.

ESX

Registra sul server, attiva dal client:

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)

La funzione del server ottiene source e cb, e passi la risposta a cb. Gli argomenti extra dal client arrivano dopo cb. La funzione client riceve quello che cb ha inviato.

QBCore

I nomi differiscono, la forma è la stessa:

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)

Se ESX o QBCore è nil dentro lo script, la callback non si registra mai. Vedi ESX è nil e QBCore è nil.

ox_lib

Le callback ox_lib non hanno bisogno di un framework, e la risposta è un valore di ritorno invece di una funzione 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)

Il secondo argomento di await è un ritardo in millisecondi tra la chiamata e la risposta (usa false per nessuno). Gli argomenti per il server lo seguono:

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)

Affinché la callback esista, lo script carica ox_lib nel suo manifest:

lua
shared_script '@ox_lib/init.lua'

Senza di esso, lib è nil: vedi ox_lib init.lua non trovato.

Il server può anche chiamare un client: lib.callback.await('name', playerId, ...) sul server, con lib.callback.register sul client. Se preferisci non aspettare, lib.callback('name', false, function(result) end) prende una funzione invece.

Perché una callback ritorna nil

Quasi ogni caso è uno di questi:

  1. Il nome non corrisponde. Il registro e i nomi di attivazione devono essere identici, incluso caso. Un typo non solleva un errore che noterai, non risponde solo mai.
  2. Non è registrato. Il file del server non è mai corso: manca da server_scripts, la risorsa non si è avviata, o è fallita prima di raggiungere la riga di registrazione.
  3. Un errore sul server, prima della risposta. Se la funzione del server dà errore, per esempio xPlayer è nil, la risposta non è mai inviata. Controlla la console del server, non quella del client.
  4. Non chiami cb su ogni percorso. Su ESX e QBCore, un branch che ritorna senza chiamare cb(...) lascia il client ad aspettare:
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. Hai dimenticato return su ox_lib. Una funzione lib.callback.register che non ha return risponde nil.
  2. Chiami troppo presto. Una callback client attivata all'avvio dello script può raggiungere il server prima che il suo registro sia corso, dopo un riavvio per esempio. Attivala dopo che il giocatore è caricato.
  3. Stili misti. Una callback registrata con lib.callback.register non può essere chiamata con ESX.TriggerServerCallback. Usa la coppia corrispondente.

Suggerimento: per scoprire quale caso hai, aggiungi un print come prima riga della funzione del server. Nessun print significa step 1 o 2, un print senza risposta significa 3 a 5.

Proteggi da nil sul client

Tratta la risposta come qualcosa che può mancare:

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

Per i framework più vecchi, controlla l'argomento prima di indicizzarlo:

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

Quale usare

  • Scrivere solo per un framework: la sua callback è fine.
  • Scrivere per molti framework, o per QBox: usa ox_lib, così una callback funziona ovunque.
  • Scrivere codice nuovo: lib.callback ritorna valori e legge come una funzione normale, il che rende i errori più facili da individuare.

Se porti uno script tra ESX e QBCore, i nomi delle callback sono una riga nella mappa funzionale.

Checklist

Sintomo Soluzione
Il risultato è nil Controlla che il nome corrisponda esattamente su entrambi i lati
Non risponde mai Assicurati che il file del server sia nel manifest e la risorsa sia avviata
Errore nella console del server Correggilo; una callback fallita non invia risposta
ESX o QBCore: nessuna risposta su alcuni percorsi Chiama cb(...) su ogni branch
ox_lib: risultato nil Aggiungi return alla funzione lib.callback.register
lib è nil Aggiungi shared_script '@ox_lib/init.lua' al manifest

Risposte rapide

Qual è la differenza tra una callback e un evento?

Un evento invia un messaggio e non aspetta una risposta. Una callback chiede all'altro lato e ottiene un valore indietro, così il client può usare dati che solo il server sa.

Posso usare le callback ox_lib su ESX o QBCore?

Sì. ox_lib è indipendente dal framework, quindi lib.callback funziona su ESX, QBCore e QBox finché ox_lib è avviato e caricato dallo script.

Perché lib.callback.await ferma il mio script per un po'?

Aspetta la risposta del server, quindi cede il thread. Se il server non risponde mai perché la callback è mancante o dà errore, il thread continua ad aspettare o fallisce con un errore.

Script senza questo problema

Advanced BoostingBoosting di veicoli dal tablet: contratti dalla classe D alla S+, crew e coda in tempo reale.Vedi script →Quest CreatorUn editor visuale di missioni e dialoghi con gli NPC, costruito nodo per nodo in gioco.Vedi script →Pawn Shop AppUn banco dei pegni tra giocatori dentro lb-phone.Vedi script →

Continua a leggere