ESX es nil: cómo arreglar esx:getSharedObject en ESX Legacy
¿Te sale attempt to index a nil value (global 'ESX')? El antiguo evento esx:getSharedObject ya no existe en ESX Legacy. Aquí tienes el arreglo de una línea y qué hacer con los scripts que no puedes editar.
Arrancas el servidor, abres la consola F8 y ahí está:
SCRIPT ERROR: @my_script/client/main.lua:12: attempt to index a nil value (global 'ESX')O su gemelo en el lado del servidor, attempt to index a nil value (upvalue 'ESX'). El script está bien, ESX está funcionando y aun así ESX es nil. Es el error de ESX más común que existe, y casi siempre tiene la misma causa.
Por qué ESX es nil
Los scripts de ESX antiguos obtienen el objeto ESX así:
ESX = nil
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)Ese evento era la forma en que ESX 1.1 y 1.2 repartían su objeto compartido. ESX Legacy lo marcó como obsoleto, y las versiones actuales ya no responden a él. El script lanza el evento, nadie contesta, y ESX se queda en nil hasta que la primera línea que lo usa peta.
Lo verás sobre todo con scripts escritos hace años o copiados de tutoriales antiguos.
El arreglo: pídeselo directamente a es_extended
Sustituye esas líneas por el export que ofrece ESX Legacy:
ESX = exports['es_extended']:getSharedObject()Funciona igual en el cliente y en el servidor. Hazlo en todos los archivos que usen ESX. Si el script también tenía un bucle de espera como este, bórralo; el export responde al instante:
-- old code: remove it
Citizen.CreateThread(function()
while ESX == nil do
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
Citizen.Wait(0)
end
end)Aún más fácil: imports.lua
es_extended trae un pequeño archivo que te prepara ESX. Añádelo al fxmanifest.lua del script:
fx_version 'cerulean'
game 'gta5'
lua54 'yes'
shared_script '@es_extended/imports.lua'
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }Ahora todos los archivos de cliente y de servidor tienen un ESX global, y en el cliente ESX.PlayerData se mantiene actualizado cuando cambian el trabajo y el dinero del jugador. Puedes borrar del todo las líneas de getSharedObject.
Consejo: usa un solo método por script. O el export al principio de cada archivo, o
imports.luaen el manifest; mezclar los dos funciona, pero solo añade ruido.
¿Sigue siendo nil? Revisa el orden de arranque
Si ya usas el export y ESX sigue siendo nil, o te sale No such export getSharedObject in resource es_extended, el script está arrancando antes que es_extended. El orden lo decide tu server.cfg:
ensure oxmysql
ensure ox_lib
ensure es_extended
ensure [esx]
ensure my_scriptDos cosas más que revisar en la consola del servidor, desde el principio del todo:
- es_extended arrancó sin errores. Si falla (un
mysql_connection_stringincorrecto, falta oxmysql), todos los scripts que dependen de él fallan también. - La carpeta se llama de verdad
es_extended. Una copia renombrada o duplicada rompe el nombre del export, y en Linux el nombre distingue entre mayúsculas y minúsculas.
Explicamos ese error en detalle en No such export getSharedObject in resource es_extended.
Datos del jugador en el cliente
Los scripts antiguos también leen al jugador así:
-- old
ESX.GetPlayerData()
RegisterNetEvent('esx:playerLoaded')
AddEventHandler('esx:playerLoaded', function(xPlayer) PlayerData = xPlayer end)Eso sigue funcionando en ESX Legacy, con un detalle: espera a que el jugador esté cargado antes de leer el trabajo o el dinero al arrancar.
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)Con imports.lua, ESX.PlayerData.job se mantiene actualizado sin que hagas nada.
Scripts que no puedes editar
Si el script está encriptado (escrow) y sigue usando el evento antiguo, no puedes cambiar su código. Por orden de preferencia:
- Pídele una actualización a su autor. Cualquier script que se siga vendiendo para ESX debería usar el export.
- Responde tú mismo al evento antiguo desde ESX. En es_extended, añade esto a un archivo de servidor y a uno de cliente:
AddEventHandler('esx:getSharedObject', function(cb)
cb(ESX)
end)Cuidado: esto es un parche al propio es_extended. Al actualizar ESX se sobrescribe, así que tendrás que volver a añadirlo después de cada actualización. Úsalo como solución temporal, no como el arreglo definitivo.
Checklist rápida
| Síntoma | Solución |
|---|---|
attempt to index a nil value (global 'ESX') |
Sustituye TriggerEvent('esx:getSharedObject'…) por exports['es_extended']:getSharedObject() |
| Sigue siendo nil después del cambio | Arranca es_extended antes que el script en server.cfg |
No such export getSharedObject |
es_extended no ha arrancado, ha fallado o tiene otro nombre |
ESX.PlayerData.job es nil al arrancar |
Espera primero a ESX.IsPlayerLoaded() |
| Script encriptado con el evento antiguo | Pídeselo al autor; mientras tanto, responde al evento desde es_extended |
Respuestas rápidas
¿Por qué ESX es nil en mi script?
El script pide ESX con la antigua llamada TriggerEvent('esx:getSharedObject'), a la que ESX Legacy ya no responde. Sustitúyela por ESX = exports['es_extended']:getSharedObject(), o añade shared_script '@es_extended/imports.lua' al fxmanifest.
¿Tengo que cambiar tanto los archivos de cliente como los de servidor?
Sí. Todos los archivos que usan ESX necesitan el objeto, en el cliente y en el servidor. La línea de imports.lua en el fxmanifest los cubre todos de una vez.
¿Y si el script está encriptado (escrow) y no puedo editarlo?
Primero pídele una actualización a su autor. Como último recurso puedes responder al evento antiguo desde es_extended, pero tendrás que volver a añadirlo cada vez que actualices ESX.
Scripts que evitan este problema
Advanced BoostingBoosting de vehículos desde una tablet: contratos de clase D a S+, crews y cola en vivo.Ver script →
Item Creator V2Crea items usables con animaciones, props, efectos y más — sin escribir código.Ver script →
Shop CreatorCrea una tienda en menos de un minuto — dueños, empleados, caja fuerte y atracos.Ver script →