Exports FiveM em Lua: exports('name', fn) e 'No such export'

Como definir e chamar exports no FiveM Lua, os estilos de exports de fxmanifest e server_exports, e como corrigir erros 'No such export' causados por ordem de inicialização ou lado errado.

Um script chama outro e o console responde:

text
No such export getCount in resource my_inventory

Este artigo mostra como exports são definidas e chamadas em Lua, as duas maneiras de declará-las e as razões usuais que o erro aparece.

Definindo uma export

Uma export permite que um recurso ofereça uma função aos outros. A forma simples é a função exports dentro de um script:

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

exports('getCount', getCount)

Você também pode passar a função inline:

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

Isso é tudo. Não há nada para adicionar a fxmanifest.lua, e a export existe no lado em que o script roda: coloque-a em um script de servidor e é uma export de servidor, coloque-a em um script de cliente e é uma export de cliente.

O estilo de manifesto

Recursos mais antigos declaram exports em fxmanifest.lua e definem uma função global simples com o mesmo 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 { … } lista exports de cliente.
  • server_exports { … } lista exports de servidor.

Isso ainda funciona e muitos recursos de ESX e QBCore o usam. Os dois estilos não entram em conflito, então um recurso pode misturá-los. Para código novo, exports('name', fn) é mais simples porque a função e a export vivem juntas e você não pode esquecer uma linha no manifesto. Lembre-se de que fxmanifest.lua é o nome do manifesto atual: veja fxmanifest vs __resource.lua.

Chamando uma export

De qualquer outro recurso no mesmo lado:

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

As versões com ponto e dois-pontos são a mesma coisa, contanto que o nome seja um identificador Lua válido:

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

Use a forma de colchetes quando o nome do recurso tem um travessão, como exports['qb-core']:GetCoreObject(). A chamada é síncrona: retorna o valor da função e pode ceder se a função espera.

Dica: argumentos e valores de retorno viajam entre recursos, então tabelas são copiadas. Alterar uma tabela que você recebeu de uma export não altera os próprios dados do outro recurso. Funções dentro de uma tabela retornada ainda funcionam, pois chamam de volta para o proprietário.

Por que você recebe "No such export"

text
No such export getCount in resource my_inventory

Verifique estes, nesta ordem:

  1. O recurso não está iniciado. Abra o console e execute ensure my_inventory. Se falhar ao iniciar, corrija isso primeiro.
  2. Iniciou após o chamador. A export só existe uma vez que o proprietário carregou seus scripts. Veja ordem de inicialização em server.cfg e coloque o proprietário acima dos scripts que a usam.
  3. O nome está escrito errado. Os nomes de export diferenciam maiúsculas de minúsculas: getCount e GetCount são diferentes.
  4. Lado errado. Um script de servidor não pode chamar uma export de cliente e vice-versa. O erro parece o mesmo.
  5. A export é declarada mas a função está faltando. Com o estilo de manifesto, server_exports { 'getCount' } precisa de uma função global chamada getCount no servidor. Uma função local não conta.
  6. O proprietário falhou ou foi parado. Se ele travou em um erro de script ou você o parou, suas exports desapareceram até rodar novamente. Leia seu resultado de inicialização no console.

Para as versões do mundo real deste erro, veja No such export GetSharedObject in resource es_extended e QBCore is nil: GetCoreObject.

Faça a ordem certa com dependências

Não confie apenas na ordem das linhas ensure. Declare a dependência no manifesto do script que chama a export:

lua
dependency 'my_inventory'

FiveM então inicia my_inventory primeiro e se recusa a iniciar seu recurso se estiver faltando, com uma mensagem mais clara (could not find dependency).

Tratando um recurso faltante com elegância

Se outro recurso é opcional, verifique seu estado antes de chamá-lo:

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

GetResourceState retorna uma string como started, stopped, starting ou missing. É a forma limpa de suportar uma integração opcional sem um erro no console.

Chamando suas próprias exports

Um recurso pode chamar suas próprias exports também, com seu próprio nome: exports['my_inventory']:getCount(...). Para uma função que é usada apenas dentro do recurso, uma função local normal é mais rápida e simples. Exports são para o limite entre recursos.

Uma palavra sobre performance

Cada chamada cruza entre dois recursos, então é mais lenta que uma chamada de função normal. Não chame uma export em um loop apertado por frame se você pode ler o valor uma vez e mantê-lo. Chamar uma algumas vezes por segundo é bom.

Lista de verificação

Sintoma Correção
No such export x in resource y Inicie y e coloque-o antes do chamador em server.cfg
Funciona no servidor, falha no cliente Defina a export em um script de cliente também, ou chame-a do servidor
Export de estilo manifesto faltando Defina uma função global com o mesmo nome que a entrada de manifesto
Caso de nome diferente Combine a ortografia exatamente
Nome do recurso tem um travessão exports['my-resource']:name()
Integração opcional spamma o console Verifique GetResourceState('x') == 'started' primeiro

Respostas rápidas

Como chamo uma export de outro recurso?

Use exports['resource_name']:exportName(args) ou exports.resource_name:exportName(args). O outro recurso deve estar iniciado e deve definir aquele export no mesmo lado (cliente ou servidor).

Ainda preciso de exports no fxmanifest.lua?

Não com exports('name', fn): registra a export do próprio script. As listas exports {} e server_exports {} no manifesto são o estilo mais antigo, onde uma função global é exposta por nome.

Por que uma export funciona no cliente mas não no servidor?

Exports de cliente e servidor são separados. Uma export definida em um script de cliente só existe no cliente, e uma definida em um script de servidor só no servidor.

Scripts sem esse problema

Item Creator V2Crie itens usáveis com animações, props, efeitos e muito mais — sem escrever código.Ver script →Mic PhoneUm celular dobrável que abre em tablet e chega ao celular de verdade do jogador.Ver script →Shop CreatorMonte uma loja em menos de um minuto — donos, funcionários, cofres e assaltos inclusos.Ver script →

Continue lendo