Exporty FiveM w Lua: exports('name', fn) i « No such export »

Jak definiować i wywoływać exporty w Lua FiveM, style fxmanifest exports i server_exports oraz jak naprawić błędy « No such export » spowodowane kolejnością startu lub złą stroną.

Skrypt wzywa inny, a konsola odpowiada:

text
No such export getCount in resource my_inventory

Ten artykuł pokazuje, jak exporty są definiowane i wywoływane w Lua, dwie sposoby ich deklaracji i zwykłe powody, że błąd się pojawia.

Definiowanie exportu

Export pozwala jednemu zasobowi oferować funkcję innym. Prostym sposobem jest funkcja exports wewnątrz skryptu:

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

exports('getCount', getCount)

Możesz również przekazać funkcję wewnątrz:

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

To wszystko. Nie ma nic do dodania do fxmanifest.lua, i export istnieje na stronie, którą uruchamia skrypt: umieść go w skrypcie serwera i to jest export serwera, umieść go w skrypcie klienta i to jest export klienta.

Styl manifestu

Starsze zasoby deklarują exporty w fxmanifest.lua i definiują zwykłą globalną funkcję o tej samej nazwie:

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

server_exports { 'getCount' }
exports { 'getOwnedCount' }
lua
-- server script
function getCount(source, item)
    return 5
end
  • exports { … } wyświetla klienckie exporty.
  • server_exports { … } wyświetla serwerowe exporty.

To wciąż działa, i wiele zasobów ESX i QBCore go używa. Dwa style się nie konfliktują, więc zasób może je mieszać. Dla nowego kodu, exports('name', fn) jest prostszy, ponieważ funkcja i export mieszkają razem, i nie możesz zapomnieć linię w manifeście. Pamiętaj, że fxmanifest.lua to nazwa aktualnego manifestu: patrz fxmanifest vs __resource.lua.

Wywoływanie exportu

Z każdego innego zasobu po tej samej stronie:

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

Wersje z kropką i dwukropkiem to to samo, o ile nazwa jest prawidłowym identyfikatorem Lua:

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

Używaj formy nawiasu, gdy nazwa zasobu ma myślnik, takie jak exports['qb-core']:GetCoreObject(). Wezwanie jest synchroniczne: zwraca wartość funkcji i może mieć opóźnienie, jeśli funkcja czeka.

Porada: argumenty i zwracane wartości podróżują między zasobami, więc tabele są kopiowane. Zmiana tabeli, którą otrzymałeś z exportu, nie zmienia własnych danych innego zasobu. Funkcje wewnątrz zwróconej tabeli wciąż działają, ponieważ odwołują się z powrotem do właściciela.

Dlaczego dostajesz « No such export »

text
No such export getCount in resource my_inventory

Sprawdzić to, w tej kolejności:

  1. Zasób nie jest uruchomiony. Otwórz konsolę i uruchom ensure my_inventory. Jeśli uruchamia się nie powiedzie, napraw to najpierw.
  2. Uruchomił się po dzwoniącym. Export istnieje dopiero po załadowaniu skryptów właściciela. Patrz start order in server.cfg i umieść właściciela powyżej skryptów, które go używają.
  3. Nazwa jest źle napisana. Nazwy exportu są czułe na wielkość liter: getCount i GetCount to różne rzeczy.
  4. Zła strona. Skrypt serwera nie może wezwać export klienta i odwrotnie. Błąd wygląda tak samo.
  5. Export jest deklarowany, ale funkcja brakuje. Ze stylem manifestu, server_exports { 'getCount' } potrzebuje globalnej funkcji o nazwie getCount na serwerze. Lokalna funkcja się nie liczy.
  6. Właściciel się nie powiedzie lub został zatrzymany. Jeśli upadł na błąd skryptu, lub go zatrzymałeś, jego exporty są znikęły, dopóki nie uruchomi się ponownie. Przeczytaj jego dane wyjściowe startu w konsoli.

W przypadku rzeczywistych wersji tego błędu, patrz No such export GetSharedObject in resource es_extended i QBCore is nil: GetCoreObject.

Upewniaj się w kolejności zależnościami

Nie polegaj tylko na kolejności linii ensure. Zadeklaruj zależność w manifeście skryptu, który wzywa export:

lua
dependency 'my_inventory'

FiveM następnie uruchamia my_inventory najpierw, i odmawia uruchomienia twojego zasobu, jeśli brakuje, z jaśniejszą wiadomością (could not find dependency).

Elegancko obsługuj brakujący zasób

Jeśli inny zasób jest opcjonalny, sprawdzić jego stan przed wezwaniem go:

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

GetResourceState zwraca ciąg taki jak started, stopped, starting lub missing. To czysty sposób na wspieranie opcjonalnej integracji bez błędu konsoli.

Wywoływanie własnych exportów

Zasób może również wywoływać własne exporty, z własną nazwą: exports['my_inventory']:getCount(...). Dla funkcji, która jest używana tylko wewnątrz zasobu, normalna lokalna funkcja jest szybsza i prostsza. Exporty są dla granicy między zasobami.

Słowo o wydajności

Każde wezwanie przecina między dwoma zasobami, więc jest wolniejsze niż normalne wezwanie funkcji. Nie wywoływaj exportu w ścisłej per-ramkowej pętli, jeśli możesz przeczytać wartość raz i ją trzymać. Wezwanie jednego kilka razy na sekundę jest w porządku.

Lista kontrolna

Objaw Naprawa
No such export x in resource y Uruchom y i umieść go przed dzwoniącym w server.cfg
Działa na serwerze, nie powiedzie się na kliencie Definiuj export w skrypcie klienta także, lub wezwij go z serwera
Eksport stylu manifestu brakuje Definiuj globalną funkcję o tej samej nazwie co wpis manifestu
Przypadek nazwy różnię Dopasuj pisowni dokładnie
Nazwa zasobu ma myślnik exports['my-resource']:name()
Opcjonalna integracja spamuje konsolę Sprawdzić GetResourceState('x') == 'started' najpierw

Szybkie odpowiedzi

Jak wezwę export z innego zasobu?

Użyj exports['resource_name']:exportName(args) lub exports.resource_name:exportName(args). Inny zasób musi być uruchomiony i musi definiować ten export na tej samej stronie (klient lub serwer).

Czy wciąż potrzebuję exportów w fxmanifest.lua?

Nie z exports('name', fn): to rejestruje export z samego skryptu. Listy exports {} i server_exports {} w manifeście to starszy styl, gdzie globalna funkcja jest ujawniana po nazwie.

Dlaczego export działa na kliencie, ale nie na serwerze?

Exporty klienta i serwera są oddzielne. Export zdefiniowany w skrypcie klienta istnieje tylko na kliencie, a zdefiniowany w skrypcie serwera tylko na serwerze.

Skrypty bez tego problemu

Item Creator V2Twórz używalne przedmioty z animacjami, propami, efektami i nie tylko — bez pisania kodu.Zobacz skrypt →Mic PhoneSkładany telefon, który rozkłada się w tablet i działa też na prawdziwym telefonie gracza.Zobacz skrypt →Shop CreatorZbuduj sklep w niecałą minutę — właściciele, pracownicy, sejfy i napady w zestawie.Zobacz skrypt →

Czytaj dalej