attempt to index a nil value (local 'Player'): QBCore e QBox fix
Player é nil em seu script QBCore ou QBox? Por que QBCore.Functions.GetPlayer(source) retorna nil, lookups de citizenid apenas para jogadores online, e os padrões de guarda segura.
No console do server:
SCRIPT ERROR: @my_script/server/main.lua:27: attempt to index a nil value (local 'Player')local Player = QBCore.Functions.GetPlayer(source)
Player.Functions.AddMoney('cash', 100) -- Player is nilGetPlayer não encontrou jogador carregado para aquele id e retornou nil, e a próxima linha o indexou. As causas espelham o caso ESX em ESX xPlayer is nil, com especificidades de QBCore e QBox.
1. O jogador ainda não está carregado
Um jogador pode estar conectado antes de QBCore ter carregado seu character, especialmente enquanto uma tela de multicharacter está aberta. Até o character ser escolhido, GetPlayer(source) retorna nil.
Código que roda em playerJoining, ou de uma thread que começa imediatamente, atinge isso. Espere pelo evento QBCore que dispara quando o jogador está pronto. No server:
AddEventHandler('QBCore:Server:PlayerLoaded', function(Player)
print(Player.PlayerData.citizenid .. ' is loaded')
end)No cliente, o evento correspondente é QBCore:Client:OnPlayerLoaded:
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerLoaded = true
end)Se seu resource reinicia enquanto jogadores estão online, aqueles eventos não disparam novamente para eles. Ao iniciar, vá através dos jogadores que já estão carregados:
CreateThread(function()
for _, src in pairs(QBCore.Functions.GetPlayers()) do
local Player = QBCore.Functions.GetPlayer(src)
if Player then
-- set up the player
end
end
end)2. source mudou após um Wait
source é um global que FiveM define para o evento rodando. Se você chamar Wait dentro do handler, outro evento pode rodar e mudar.
RegisterNetEvent('my_script:sell', function()
Wait(1000)
local Player = QBCore.Functions.GetPlayer(source) -- may be wrong, or nil
end)Armazene primeiro:
RegisterNetEvent('my_script:sell', function()
local src = source
Wait(1000)
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
end)3. O id está errado
GetPlayer espera o server id de um jogador online, como um número.
- Uma string de um comando. Argumentos são texto, então converta:
QBCore.Functions.GetPlayer(tonumber(args[1])). - O id errado do cliente. No cliente,
PlayerId()é um índice local. O server id éGetPlayerServerId(PlayerId()). Melhor, ignore ids enviados pelo cliente e usesource, veja securing server events. - O console. Um comando digitado no console do server tem
sourceigual a0, que não é um jogador. - Um id que deixou. O jogador desconectou enquanto seu código esperava.
QBCore.Commands.Add('givecash', 'Give cash', { { name = 'id', help = 'Player id' }, { name = 'amount', help = 'Amount' } }, true, function(source, args)
local target = QBCore.Functions.GetPlayer(tonumber(args[1]))
local amount = tonumber(args[2])
if not target or not amount then return end
target.Functions.AddMoney('cash', amount)
end, 'admin')4. Lookups de citizenid apenas encontram jogadores online
Muitos scripts armazenam o citizenid em vez do source, porque o source muda a cada session. Para pegar o jogador de um citizenid:
local Player = QBCore.Functions.GetPlayerByCitizenId(citizenid)Isso apenas funciona enquanto aquele jogador está online e carregado. Para um jogador que está offline retorna nil, que não é um erro nos seus dados. Leia o banco de dados para jogadores offline:
local row = MySQL.single.await('SELECT charinfo, job FROM players WHERE citizenid = ?', { citizenid })
if row then
local charinfo = json.decode(row.charinfo)
endcharinfo é armazenado como texto JSON, então decodifique com segurança, veja FiveM json.decode errors. Escrever para um jogador offline é uma tarefa diferente: mude a linha do banco de dados apenas se o jogador estiver realmente offline, ou o próximo save do server sobrescreve sua mudança.
5. Em QBox
O core de QBox é qbx_core. Mantém uma compatibility layer, então QBCore.Functions.GetPlayer ainda funciona em scripts escritos para QBCore. Para código novo, use seus exports, que retornam o mesmo tipo de objeto de jogador ou nil:
local player = exports.qbx_core:GetPlayer(source)
if not player then return end
print(player.PlayerData.citizenid)Para um jogador online por citizenid:
local player = exports.qbx_core:GetPlayerByCitizenId(citizenid)As regras deste artigo se aplicam da mesma forma: sem jogador até o character ser carregado, armazene source antes de um Wait, e espere nil para um jogador offline. Se você está movendo um script entre os cores, veja converting a QBCore script to QBox.
6. playerDropped
Quando um jogador sai, qb-core salva e remove o jogador por conta própria, e a ordem de handlers para playerDropped não é algo em que confiar. Em seu próprio handler playerDropped, GetPlayer(source) pode já ser nil. Mantenha o que você precisa em sua própria tabela enquanto o jogador está online:
local sessions = {}
AddEventHandler('QBCore:Server:PlayerLoaded', function(Player)
sessions[Player.PlayerData.source] = Player.PlayerData.citizenid
end)
AddEventHandler('playerDropped', function()
local citizenid = sessions[source]
sessions[source] = nil
if citizenid then
print(citizenid .. ' left')
end
end)O padrão de guarda
Comece todo handler do server que precisa de um jogador do mesmo jeito:
RegisterNetEvent('my_script:action', function()
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
-- Player is safe to use here
end)Dica: se o erro é sobre
QBCoreem si sendo nil, o problema é o objeto core, não o jogador. Veja attempt to index a nil value (global 'QBCore').
Checklist
| Sintoma | Solução |
|---|---|
| Nil logo após o jogador entrar | Espere por QBCore:Server:PlayerLoaded em vez de playerJoining |
Nil após um Wait |
Armazene local src = source e use src |
| Nil de um comando | Converta o argumento com tonumber; o console source é 0 |
GetPlayerByCitizenId retorna nil |
O jogador está offline; query a tabela players |
| Server QBox | Use exports.qbx_core:GetPlayer(source) e cheque por nil |
Nil em playerDropped |
Mantenha os dados que você precisa em sua própria tabela enquanto o jogador está online |
| Qualquer nil | Adicione if not Player then return end no topo do handler |
Respostas rápidas
Por que QBCore.Functions.GetPlayer retorna nil?
Não há jogador carregado com aquele id. O jogador pode ainda estar carregando, o id pode estar errado ou perdido após um Wait, ou o jogador já deixou.
O GetPlayerByCitizenId funciona para jogadores offline?
Não. Apenas encontra jogadores que estão online. Para um jogador offline, leia a tabela players no banco de dados em vez disso.
Qual é o equivalente em QBox de QBCore.Functions.GetPlayer?
exports.qbx_core:GetPlayer(source). Retorna o objeto do jogador, ou nil quando não há jogador carregado para aquele id.
Scripts sem esse problema
Advanced BoostingBoosting de veículos pelo tablet: contratos da classe D à S+, crews e fila ao vivo.Ver script →
Drug Dealer AppVendas na rua como app do lb-phone: zonas, compradores NPC, níveis e alertas para a polícia.Ver script →
Pawn Shop AppUma casa de penhores entre jogadores dentro do lb-phone.Ver script →