ESX to nil: naprawianie esx:getSharedObject w ESX Legacy

attempt to index a nil value (global 'ESX')? Stare wydarzenie esx:getSharedObject zniknęło z ESX Legacy. Oto jednowierszowa poprawka i co zrobić ze skryptami, których nie można edytować.

Uruchamiasz serwer, otwierasz konsolę F8 i gotowe:

text
SCRIPT ERROR: @my_script/client/main.lua:12: attempt to index a nil value (global 'ESX')

Lub bliźniak po stronie serwera, attempt to index a nil value (upvalue 'ESX'). Skrypt jest w porządku, ESX działa, a ESX nadal wynosi nil. Jest to najczęstszy błąd ESX i prawie zawsze ma tę samą przyczynę.

Dlaczego ESX to nil

Starsze skrypty ESX pobierają obiekt ESX w następujący sposób:

lua
ESX = nil

TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)

To wydarzenie polegało na tym, jak ESX 1.1 i 1.2 przekazały swój wspólny obiekt. ESX Legacy zostało uznane za przestarzałe i obecne wersje już na to nie odpowiadają. Skrypt wyzwala zdarzenie, nikt nie odpowiada, a ESX pozostaje nil do czasu awarii pierwszej linii, która go używa.

Zobaczysz to głównie w przypadku skryptów napisanych wiele lat temu lub skopiowanych ze starych tutoriali.

Poprawka: zapytaj es_extended bezpośrednio

Zastąp te linie eksportem ESX Legacy, który zapewnia:

lua
ESX = exports['es_extended']:getSharedObject()

Działa tak samo na kliencie i na serwerze. Zrób to w każdym pliku, który używa ESX. Jeśli skrypt również zawierał pętlę oczekiwania taką jak ta, usuń ją; eksport odpowiada od razu:

lua
-- old code: remove it
Citizen.CreateThread(function()
    while ESX == nil do
        TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
        Citizen.Wait(0)
    end
end)

Jeszcze prościej: imports.lua

es_extended dostarcza mały plik, który konfiguruje ESX za Ciebie. Dodaj go do fxmanifest.lua:

lua
fx_version 'cerulean'
game 'gta5'
lua54 'yes'

shared_script '@es_extended/imports.lua'

client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }

Teraz każdy plik klienta i serwera ma globalny ESX, a na kliencie ESX.PlayerData jest na bieżąco, gdy zmienia się praca gracza i pieniądze. Możesz całkowicie usunąć linie getSharedObject.

Wskazówka: użyj jednego podejścia na skrypt. Albo eksport na górze każdego pliku, albo imports.lua w manifeście; miksowanie obu działa, ale jest to hałas.

Nadal nil? Sprawdź kolejność rozpoczęcia

Jeśli już korzystasz z eksportu i ESX nadal wynosi nil lub otrzymujesz No such export getSharedObject in resource es_extended, skrypt uruchamia się przed es_extended. Twoje server.cfg decyduje o kolejności:

cfg
ensure oxmysql
ensure ox_lib
ensure es_extended
ensure [esx]

ensure my_script

Jeszcze dwie rzeczy do sprawdzenia w konsoli serwera, od samej góry:

  • es_extended uruchomił się bez błędów. Jeśli się nie powiedzie (złe mysql_connection_string, brakujące oxmysql), każdy skrypt od niego zależny również zakończy się niepowodzeniem.
  • Folder tak naprawdę nazywa się es_extended. Kopia o zmienionej nazwie lub zduplikowana powoduje uszkodzenie nazwy eksportu, a w systemie Linux w nazwie rozróżniana jest wielkość liter.

Szczegółowo omawiamy ten błąd w Brak takiego eksportu getSharedObject w zasobie es_extended.

Dane gracza w kliencie

Stare skrypty również czytają odtwarzacz w ten sposób:

lua
-- old
ESX.GetPlayerData()
RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function(xPlayer) PlayerData = xPlayer end)

To nadal działa w ESX Legacy, z jednym szczegółem: poczekaj, aż odtwarzacz się załaduje, zanim zaczniesz czytać zlecenie lub pieniądze przy uruchomieniu.

lua
CreateThread(function()
    while not ESX.IsPlayerLoaded() do Wait(250) end
    local job = ESX.GetPlayerData().job
    print(('job: %s (%s)'):format(job.name, job.grade))
end)

RegisterNetEvent('esx:setJob', function(job)
    -- the job changed: refresh whatever shows it
end)

Dzięki imports.lua wartość ESX.PlayerData.job jest dla Ciebie na bieżąco.

Skrypty, których nie można edytować

Jeśli skrypt jest zdeponowany (zaszyfrowany) i nadal korzysta ze starego zdarzenia, nie można zmienić jego kodu. W kolejności preferencji:

  1. Poproś autora o aktualizację. Każdy skrypt nadal sprzedawany za ESX powinien korzystać z eksportu.
  2. Odpowiedz samodzielnie na stare wydarzenie od ESX. W es_extended dodaj to do pliku serwera i pliku klienta:
lua
AddEventHandler('esx:getSharedObject', function(cb)
    cb(ESX)
end)

Ostrzeżenie: to jest poprawka do samego es_extended. Aktualizacja ESX powoduje jego zastąpienie, dlatego po każdej aktualizacji należy go dodać ponownie. Zachowaj to jako rozwiązanie tymczasowe, a nie rozwiązanie.

Krótka lista kontrolna

Objaw Napraw
attempt to index a nil value (global 'ESX') Zamień TriggerEvent('esx:getSharedObject'…) na exports['es_extended']:getSharedObject()
Nadal nil po zmianie Rozpocznij es_extended przed skryptem w server.cfg
No such export getSharedObject es_extended nie został uruchomiony, nie powiódł się lub ma inną nazwę
ESX.PlayerData.job to nil podczas uruchamiania Najpierw poczekaj na ESX.IsPlayerLoaded()
Skrypt zdeponowany ze starym wydarzeniem Zapytaj autora; w międzyczasie odpowiedz na wydarzenie z es_extended

Szybkie odpowiedzi

Dlaczego w moim skrypcie znajduje się ESX nil?

Skrypt pyta o ESX starym wywołaniem TriggerEvent('esx:getSharedObject'), które obecne ESX Legacy już nie odpowiada. Zastąp go ESX = exports['es_extended']:getSharedObject() lub dodaj shared_script '@es_extended/imports.lua' do manifestu fx.

Czy muszę zmieniać pliki klienta i serwera?

Tak. Każdy plik używający ESX potrzebuje obiektu, zarówno na kliencie, jak i na serwerze. Wiersz imports.lua w manifeście fx obejmuje je wszystkie na raz.

Co się stanie, jeśli skrypt zostanie zdeponowany i nie będzie można go edytować?

Najpierw poproś autora o aktualizację. W ostateczności możesz odpowiedzieć na stare wydarzenie z es_extended, ale musisz to dodać ponownie przy każdej aktualizacji ESX.

Skrypty bez tego problemu

Advanced BoostingBoosting pojazdów z tabletu: kontrakty od klasy D do S+, ekipy i kolejka na żywo.Zobacz skrypt →Item Creator V2Twórz używalne przedmioty z animacjami, propami, efektami i nie tylko — bez pisania kodu.Zobacz skrypt →Shop CreatorZbuduj sklep w niecałą minutę — właściciele, pracownicy, sejfy i napady w zestawie.Zobacz skrypt →

Czytaj dalej