ESX — это nil: исправление esx:getSharedObject в ESX Legacy

attempt to index a nil value (global 'ESX')? Старое событие esx:getSharedObject исчезло из ESX Legacy. Вот однострочное исправление и то, что делать со скриптами, которые вы не можете редактировать.

Вы запускаете свой сервер, открываете консоль F8 и вот оно:

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

Или серверный двойник attempt to index a nil value (upvalue 'ESX'). Сценарий в порядке, ESX работает, а ESX по-прежнему равен nil. Это самая распространенная ESX ошибка, и почти всегда она имеет одну и ту же причину.

Почему ESX — это nil

Старые сценарии ESX получают объект ESX следующим образом:

lua
ESX = nil

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

В этом событии ESX 1.1 и 1.2 раздавали свой общий объект. ESX Legacy устарел, и текущие версии больше не отвечают на него. Сценарий запускает событие, никто не отвечает, и ESX остается nil до тех пор, пока первая строка, которая его использует, не выйдет из строя.

Вы увидите это в основном в сценариях, написанных много лет назад или скопированных из старых руководств.

Исправление: спросите es_extended напрямую

Замените эти строки экспортом, который ESX Legacy предоставляет:

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

Это работает одинаково и на клиенте, и на сервере. Сделайте это в каждом файле, который использует ESX. Если в сценарии также имеется такой цикл ожидания, удалите его; экспорт отвечает сразу:

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)

Еще проще: imports.lua

es_extended отправляет вам небольшой файл, который настраивает ESX. Добавьте его в fxmanifest.lua:

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

shared_script '@es_extended/imports.lua'

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

Теперь каждый файл клиента и сервера имеет глобальный файл ESX, и на клиенте ESX.PlayerData остается в курсе изменений работы и денег игрока. Вы можете полностью удалить строки getSharedObject.

Совет: используйте один подход для каждого сценария. Либо экспорт в верхней части каждого файла, либо imports.lua в манифесте; смешивание обоих работает, но это шум.

Все еще nil? Проверьте порядок старта

Если вы уже используете экспорт, а ESX по-прежнему имеет значение nil или вы получаете No such export getSharedObject in resource es_extended, сценарий запускается раньше es_extended. Ваш server.cfg определяет порядок:

cfg
ensure oxmysql
ensure ox_lib
ensure es_extended
ensure [esx]

ensure my_script

Еще две вещи, которые нужно проверить в консоли сервера, сверху:

  • es_extended запустился без ошибок. В случае сбоя (неправильный mysql_connection_string, отсутствующий oxmysql) каждый скрипт, зависящий от него, также завершается сбоем.
  • На самом деле папка называется es_extended. Переименованная или дублированная копия нарушает имя экспорта, а в Linux имя чувствительно к регистру.

Мы подробно рассмотрим эту ошибку в разделе Нет такого экспорта getSharedObject в ресурсе es_extended.

Данные игрока в клиенте

Старые скрипты также читают проигрыватель следующим образом:

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

Это по-прежнему работает в ESX Legacy, с одной деталью: подождите, пока плеер загрузится, прежде чем читать задание или деньги при запуске.

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)

Благодаря imports.lua ESX.PlayerData.job будет оставаться актуальным для вас.

Скрипты, которые нельзя редактировать

Если сценарий депонирован (зашифрован) и по-прежнему использует старое событие, вы не можете изменить его код. В порядке предпочтения:

  1. Попросите его автора предоставить обновленную информацию. Любой сценарий, который все еще продается за ESX, должен использовать экспорт.
  2. Ответьте на старое событие от ESX самостоятельно. В es_extended добавьте это в файл сервера и в файл клиента:
lua
AddEventHandler('esx:getSharedObject', function(cb)
    cb(ESX)
end)

Внимание: это патч для самого es_extended. При обновлении ESX он перезаписывается, поэтому вам придется добавлять его заново после каждого обновления. Используйте это как временную меру, а не как решение проблемы.

Краткий контрольный список

Симптом Исправить
attempt to index a nil value (global 'ESX') Замените TriggerEvent('esx:getSharedObject'…) на exports['es_extended']:getSharedObject()
Все еще nil после изменения Запустите es_extended перед сценарием в server.cfg
No such export getSharedObject es_extended не запущен, произошел сбой или имеет другое имя
ESX.PlayerData.job – nil при запуске Сначала подождите ESX.IsPlayerLoaded()
Сценарий депонирования со старым событием Спросите автора; тем временем ответьте на событие от es_extended

Короткие ответы

Почему ESX nil в моем скрипте?

Скрипт запрашивает ESX со старым вызовом TriggerEvent('esx:getSharedObject'), на который текущий ESX Legacy больше не отвечает. Замените его на ESX = exports['es_extended']:getSharedObject() или добавьте shared_script '@es_extended/imports.lua' в fxmanifest.

Нужно ли мне изменять файлы клиента и сервера?

Да. Каждому файлу, использующему ESX, нужен объект как на клиенте, так и на сервере. Строка imports.lua в fxmanifest охватывает все из них одновременно.

Что делать, если сценарий депонирован и я не могу его редактировать?

Сначала попросите автора обновленную информацию. В крайнем случае вы можете ответить на старое событие из es_extended, но вам придется добавлять его обратно каждый раз при обновлении ESX.

Скрипты без этой проблемы

Advanced BoostingУгон машин на заказ через планшет: контракты от класса D до S+, команды и живая очередь.Смотреть скрипт →Item Creator V2Создавайте используемые предметы с анимациями, пропами, эффектами и не только — без кода.Смотреть скрипт →Shop CreatorМагазин меньше чем за минуту — владельцы, сотрудники, сейфы и ограбления в комплекте.Смотреть скрипт →

Читайте также