attempt to index a nil value (local 'Player'): QBCore i QBox naprawa

Player jest nil w twoim skrypcie QBCore lub QBox? Dlaczego QBCore.Functions.GetPlayer(source) zwraca nil, wyszukiwania citizenid tylko dla graczy online i bezpieczne wzory ochrony.

W konsoli serwera:

text
SCRIPT ERROR: @my_script/server/main.lua:27: attempt to index a nil value (local 'Player')
lua
local Player = QBCore.Functions.GetPlayer(source)
Player.Functions.AddMoney('cash', 100)   -- Player is nil

GetPlayer nie znalazł załadowanego gracza dla tego id i zwrócił nil, a następna linia go indeksowała. Przyczyny odbijają przypadek ESX w ESX xPlayer is nil, z specyficznością QBCore i QBox.

1. Gracz nie jest jeszcze załadowany

Gracz może być połączony, zanim QBCore załaduje jego postać, szczególnie gdy ekran multicharacter jest otwarty. Dopóki postać nie zostanie wybrana, GetPlayer(source) zwraca nil.

Kod, który działa na playerJoining, lub ze wątku, który się natychmiast uruchamia, to trafia. Czekaj na zdarzenie QBCore, które się wypalnia, gdy gracz jest gotów. Na serwerze:

lua
AddEventHandler('QBCore:Server:PlayerLoaded', function(Player)
    print(Player.PlayerData.citizenid .. ' is loaded')
end)

Na kliencie, pasujące zdarzenie to QBCore:Client:OnPlayerLoaded:

lua
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
    PlayerLoaded = true
end)

Jeśli twój zasób uruchamia ponownie, podczas gdy gracze są online, te zdarzenia nie wypalają się dla nich ponownie. Przy starcie, przejdź przez graczy, którzy są już załadowani:

lua
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 zmienił się po Wait

source to globalny, który FiveM ustawia dla działającego zdarzenia. Jeśli wezwiesz Wait wewnątrz handlera, inne zdarzenie może się uruchomić i zmienić go.

lua
RegisterNetEvent('my_script:sell', function()
    Wait(1000)
    local Player = QBCore.Functions.GetPlayer(source)   -- may be wrong, or nil
end)

Zapisz to najpierw:

lua
RegisterNetEvent('my_script:sell', function()
    local src = source
    Wait(1000)

    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end
end)

3. Id jest zły

GetPlayer oczekuje server id gracza online, jako liczby.

  • Ciąg z polecenia. Argumenty to tekst, więc je konwertuj: QBCore.Functions.GetPlayer(tonumber(args[1])).
  • Zły id z klienta. Na kliencie, PlayerId() jest indeksem lokalnym. Server id to GetPlayerServerId(PlayerId()). Lepiej, zignoruj id wysłane przez klienta i użyj source, zobacz zabezpieczanie zdarzeń serwerowych.
  • Konsola. Polecenie wpisane w konsoli serwera ma source równy 0, co nie jest graczem.
  • Id, które odeszło. Gracz się rozłączył, podczas gdy twój kod czekał.
lua
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. Wyszukiwania citizenid znajdują tylko graczy online

Wiele skryptów przechowuje citizenid zamiast source, ponieważ source zmienia się na każdej sesji. Aby uzyskać gracza z citizenid:

lua
local Player = QBCore.Functions.GetPlayerByCitizenId(citizenid)

To działa tylko, podczas gdy ten gracz jest online i załadowany. Dla gracza offline zwraca nil, co nie jest błędem w twoich danych. Przeczytaj bazę danych dla graczy offline:

lua
local row = MySQL.single.await('SELECT charinfo, job FROM players WHERE citizenid = ?', { citizenid })
if row then
    local charinfo = json.decode(row.charinfo)
end

charinfo jest przechowywana jako tekst JSON, więc dekoduj ją bezpiecznie, zobacz FiveM json.decode errors. Pisanie do gracza offline to inna praca: zmień wiersz bazy danych tylko jeśli gracz jest naprawdę offline, lub następny zapis z serwera przepiszę twoją zmianę.

5. Na QBox

Core QBox to qbx_core. Utrzymuje warstwę kompatybilności, więc QBCore.Functions.GetPlayer wciąż działa w skryptach napisanych dla QBCore. Dla nowego kodu, użyj jego eksportów, które zwracają ten sam rodzaj obiektu gracza lub nil:

lua
local player = exports.qbx_core:GetPlayer(source)
if not player then return end

print(player.PlayerData.citizenid)

Dla gracza online po citizenid:

lua
local player = exports.qbx_core:GetPlayerByCitizenId(citizenid)

Reguły z tego artykułu dotyczą w taki sam sposób: żaden gracz, dopóki postać nie będzie załadowana, magazyn source przed Wait i oczekuje nil dla gracza offline. Jeśli przenosisz skrypt między rdzeniami, zobacz konwersja skryptu QBCore do QBox.

6. playerDropped

Gdy gracz odchodzi, qb-core zapisuje i usuwa gracza samodzielnie, a kolejność handlerów dla playerDropped nie jest czymś, na czym można polegać. W twoim własnym handleru playerDropped, GetPlayer(source) może już być nil. Zachowaj to, czego potrzebujesz, we własnej tabeli, podczas gdy gracz jest online:

lua
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)

Wzór ochrony

Zacznij każdy handler serwera, który potrzebuje gracza, w ten sam sposób:

lua
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)

Wskazówka: jeśli błąd dotyczy QBCore będącego nil, problem jest obiektem core, nie graczem. Zobacz attempt to index a nil value (global 'QBCore').

Lista kontrolna

Symptom Naprawa
Nil zaraz po dołączeniu gracza Czekaj na QBCore:Server:PlayerLoaded zamiast playerJoining
Nil po Wait Zapisz local src = source i użyj src
Nil z polecenia Konwertuj argument za pomocą tonumber; konsola source to 0
GetPlayerByCitizenId zwraca nil Gracz jest offline; zapytaj tabelę players
Serwer QBox Użyj exports.qbx_core:GetPlayer(source) i sprawdź nil
Nil w playerDropped Zachowaj dane, których potrzebujesz, w swojej tabeli, podczas gdy gracz jest online
Dowolny nil Dodaj if not Player then return end na górze handlera

Szybkie odpowiedzi

Dlaczego QBCore.Functions.GetPlayer zwraca nil?

Nie ma załadowanego gracza z tym id. Gracz może wciąż ładować, id może być zły lub utracony po Wait, lub gracz już odszedł.

Czy GetPlayerByCitizenId działa dla gracza offline?

Nie. Znajduje tylko graczy online. Dla gracza offline, zamiast tego przeczytaj tabelę players w bazie danych.

Jaki jest odpowiednik QBox dla QBCore.Functions.GetPlayer?

exports.qbx_core:GetPlayer(source). Zwraca obiekt gracza, lub nil, gdy nie ma załadowanego gracza dla tego id.

Skrypty bez tego problemu

Advanced BoostingBoosting pojazdów z tabletu: kontrakty od klasy D do S+, ekipy i kolejka na żywo.Zobacz skrypt →Drug Dealer AppUliczna sprzedaż jako aplikacja lb-phone: strefy, kupcy NPC, poziomy i alerty dla policji.Zobacz skrypt →Pawn Shop AppLombard między graczami wewnątrz lb-phone.Zobacz skrypt →

Czytaj dalej