Export di FiveM in Lua: exports('name', fn) e 'Nessun tale export'

Come definire e chiamare export in FiveM Lua, gli stili fxmanifest exports e server_exports, e come risolvere gli errori 'Nessun tale export' causati da ordine di avvio o il lato sbagliato.

Uno script chiama un altro e la console risponde:

text
No such export getCount in resource my_inventory

Questo articolo mostra come gli export sono definiti e chiamati in Lua, i due modi per dichiararli, e i motivi soliti per cui quell'errore appare.

Definire un export

Un export consente a una risorsa di offrire una funzione alle altre. Il modo semplice è la funzione exports dentro uno script:

lua
-- my_inventory/server/main.lua
local function getCount(source, item)
    -- ...
    return 5
end

exports('getCount', getCount)

Puoi anche passare la funzione inline:

lua
exports('getCount', function(source, item)
    return 5
end)

Questo è tutto. Non c'è niente da aggiungere a fxmanifest.lua, e l'export esiste su qualunque lato lo script viene eseguito: mettilo in uno script server e è un export server, mettilo in uno script client e è un export client.

Lo stile manifest

Le risorse più vecchie dichiarano export in fxmanifest.lua e definiscono una funzione globale semplice con lo stesso nome:

lua
-- fxmanifest.lua
fx_version 'cerulean'
game 'gta5'

server_exports { 'getCount' }
exports { 'getOwnedCount' }
lua
-- server script
function getCount(source, item)
    return 5
end
  • exports { … } elenca client export.
  • server_exports { … } elenca server export.

Questo funziona ancora, e molte risorse di ESX e QBCore lo usano. I due stili non entrano in conflitto, quindi una risorsa può mescolarli. Per il nuovo codice, exports('name', fn) è più semplice perché la funzione e l'export vivono insieme, e non puoi dimenticare una riga nel manifest. Ricorda che fxmanifest.lua è il nome del manifest attuale: vedi fxmanifest vs __resource.lua.

Chiamare un export

Da qualsiasi altra risorsa nello stesso lato:

lua
local count = exports['my_inventory']:getCount(source, 'water')

Le versioni punto e due punti sono la stessa cosa, finché il nome è un identificatore Lua valido:

lua
local count = exports.my_inventory:getCount(source, 'water')

Usa la forma tra parentesi quando il nome della risorsa ha un trattino, come exports['qb-core']:GetCoreObject(). La chiamata è sincrona: restituisce il valore della funzione, e può attendere se la funzione aspetta.

Suggerimento: gli argomenti e i valori di ritorno viaggiano tra le risorse, quindi le tabelle vengono copiate. Modificare una tabella ottenuta da un export non cambia i dati propri dell'altra risorsa. Le funzioni all'interno di una tabella restituita funzionano ancora, poiché richiamano il proprietario.

Perché ricevi "Nessun tale export"

text
No such export getCount in resource my_inventory

Controlla questi, in questo ordine:

  1. La risorsa non è avviata. Apri la console ed esegui ensure my_inventory. Se non riesce ad avviarsi, correggilo prima.
  2. Si è avviato dopo il chiamante. L'export esiste solo una volta che il proprietario ha caricato i suoi script. Vedi ordine di avvio in server.cfg e metti il proprietario sopra gli script che lo usano.
  3. Il nome è male scritto. I nomi degli export distinguono tra maiuscole e minuscole: getCount e GetCount sono diversi.
  4. Lato sbagliato. Uno script server non può chiamare un export client, e viceversa. L'errore sembra lo stesso.
  5. L'export è dichiarato ma la funzione manca. Con lo stile manifest, server_exports { 'getCount' } ha bisogno di una funzione globale chiamata getCount sul server. Una funzione locale non conta.
  6. Il proprietario ha fallito o è stato fermato. Se si è bloccato su un errore di script, o lo hai fermato, i suoi export sono spariti fino al prossimo esecuzione. Leggi il suo output di avvio nella console.

Per le versioni nel mondo reale di questo errore, vedi Nessun tale export GetSharedObject in risorsa es_extended e QBCore è nil: GetCoreObject.

Rendi sicuro l'ordine con dipendenze

Non fare affidamento solo sull'ordine delle linee ensure. Dichiara la dipendenza nel manifest dello script che chiama l'export:

lua
dependency 'my_inventory'

FiveM quindi avvia my_inventory per primo, e rifiuta di avviare la tua risorsa se manca, con un messaggio più chiaro (non è stato possibile trovare la dipendenza).

Gestione di una risorsa mancante con eleganza

Se un'altra risorsa è opzionale, controlla il suo stato prima di chiamarla:

lua
if GetResourceState('my_inventory') == 'started' then
    local count = exports.my_inventory:getCount(source, 'water')
end

GetResourceState restituisce una stringa come started, stopped, starting o missing. È il modo pulito per supportare un'integrazione opzionale senza un errore della console.

Chiamare i tuoi stessi export

Una risorsa può chiamare anche i suoi stessi export, con il suo nome: exports['my_inventory']:getCount(...). Per una funzione che viene utilizzata solo all'interno della risorsa, una funzione locale normale è più veloce e più semplice. Gli export sono per il confine tra le risorse.

Una parola sulla prestazione

Ogni chiamata attraversa le risorse, quindi è più lenta di una normale chiamata di funzione. Non chiamare un export in un ciclo tight per frame se puoi leggere il valore una volta e mantenerlo. Chiamarne uno poche volte al secondo va bene.

Checklist

Sintomo Soluzione
No such export x in resource y Avvia y, e mettilo prima del chiamante in server.cfg
Funziona sul server, fallisce sul client Definisci l'export anche in uno script client, o chiamalo dal server
Export di stile manifest mancante Definisci una funzione globale con lo stesso nome della voce manifest
Le maiuscole e minuscole del nome differiscono Abbina l'ortografia esattamente
Il nome della risorsa ha un trattino exports['my-resource']:name()
L'integrazione opzionale spamma la console Controlla prima GetResourceState('x') == 'started'

Risposte rapide

Come chiamo un export da un'altra risorsa?

Usa exports['resource_name']:exportName(args) o exports.resource_name:exportName(args). L'altra risorsa deve essere avviata e deve definire quell'export nello stesso lato (client o server).

Ho ancora bisogno di export in fxmanifest.lua?

No con exports('name', fn): registra l'export dallo script stesso. Gli elenchi exports {} e server_exports {} nel manifest sono lo stile più vecchio, dove una funzione globale è esposta per nome.

Perché un export funziona sul client ma non sul server?

Gli export client e server sono separati. Un export definito in uno script client esiste solo sul client, e uno definito in uno script server solo sul server.

Script senza questo problema

Item Creator V2Crea oggetti utilizzabili con animazioni, props, effetti e altro — senza scrivere codice.Vedi script →Mic PhoneUn telefono pieghevole che si apre in un tablet e arriva sul telefono vero del giocatore.Vedi script →Shop CreatorCrea un negozio in meno di un minuto — proprietari, dipendenti, casseforti e rapine inclusi.Vedi script →

Continua a leggere