FiveM playerConnecting ve deferrals: defer, update, done açıklaması

AddEventHandler('playerConnecting') nasıl çalışır deferrals ile: defer, Wait(0), update, done(reason), adaptive cards ve oyuncuların done çağrısını unuttunuzda neden takıldığı.

Bir oyuncu içeri alınmadan önce bir şeyi çalıştırmak istiyorsunuz: beyaz liste kontrolü, yasaklı liste, veritabanı araması, hoş geldin kartı. Bunun yeri playerConnecting olayıdır ve araç deferrals'dir. Yanlış kullanıldığında, oyuncular bağlantı ekranında sonsuza kadar oturur, bu nedenle detaylar önemlidir.

lua
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
    -- runs when a player starts connecting
end)

Argümanlar ne

  • name: oyuncunun adı.
  • setKickReason(reason): bir iletiyle bağlantıyı reddeden bir işlev. Basit, hemen reddetmeler için mevcuttur.
  • deferrals: bağlantıyı duraklatamanıza ve çalışırken oyuncuya konuşmanıza izin veren işlevleri olan bir nesne.

İşleyicinin içinde, source oyuncunun bağlantı kimliğidir.

Dört erteleme çağrısı

lua
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
    local src = source          -- save it now

    deferrals.defer()           -- 1. pause the connection
    Wait(0)                     -- 2. let the engine register it

    deferrals.update('Checking your account...')   -- 3. show a message

    -- do your checks here

    deferrals.done()            -- 4. let the player in
end)
  1. deferrals.defer() FiveM'e oyuncuyu karar verinceye kadar tutmasını söyler. Olmadan, asenkron bir görev başlatsanız bile, işleyici döndüğü anda oyuncu izin verilir.
  2. Wait(0) defer() hemen sonrasında gereklidir. defer ile aynı işarette update, done veya presentCard çağrıları çalışmayabilir.
  3. deferrals.update(message) oyuncunun bağlantı ekranında gördüğü metni değiştirir. İlerleme göstermek için kullanın.
  4. deferrals.done(reason) beklemeyi sona erdirir. Argüman yok oyuncunun kabul edildiği anlamına gelir. Bir dize onların reddedildiği ve o dizeyi gördükleri anlamına gelir.

İpucu: source'u çok başında yerel olarak kopyalayın. Wait veya HTTP isteğinden sonra, genel source başka bir oyuncuyu işaret edebilir.

Oyuncu reddetme

lua
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
    local src = source
    deferrals.defer()
    Wait(0)

    local license
    for _, id in ipairs(GetPlayerIdentifiers(src)) do
        if id:sub(1, 8) == 'license:' then license = id break end
    end

    if not license then
        return deferrals.done('No Rockstar license found. Restart the game and try again.')
    end

    deferrals.done()
end)

return deferrals.done(...) aynı zamanda işleyiciyi sonlandırır ve done'ı iki kez çağırmaktan kaçınır.

Asenkron kontroller

Ertelemeler zaman alan iş için yapılır: bir veritabanı sorgusu veya HTTP çağrısı. Bağlantıyı ertelenmiş tutun ve geri çağırımda done çağırın.

lua
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
    local src = source
    deferrals.defer()
    Wait(0)
    deferrals.update('Looking you up...')

    local license = GetPlayerIdentifierByType(src, 'license')

    MySQL.scalar('SELECT 1 FROM whitelist WHERE license = ?', { license }, function(found)
        if found then
            deferrals.done()
        else
            deferrals.done('You are not whitelisted.')
        end
    end)
end)

GetPlayerIdentifierByType mevcut sunucu yapılarında mevcuttur. Eser eski ise, bunun yerine GetPlayerIdentifiers üzerinde döngü yapın. Sorgu sözdizimi için oxmysql guide bölümüne bakın. Discord rolleriyle tam bir örnek Discord whitelist for FiveM bölümündedir.

Yaygın hata: done unutmak

Bağlantı ekranında takılı oyuncular neredeyse her zaman bir kod yolunun hiçbir zaman deferrals.done ulaşmadığı anlamına gelir.

lua
-- Bad: nothing happens when the query returns no row
MySQL.single('SELECT * FROM bans WHERE license = ?', { license }, function(row)
    if row then
        deferrals.done('You are banned.')
    end
end)

Eğer row nil ise, oyuncu sonsuza kadar tutulur. Çözüm bir else'dir:

lua
MySQL.single('SELECT * FROM bans WHERE license = ?', { license }, function(row)
    if row then
        deferrals.done('You are banned.')
    else
        deferrals.done()
    end
end)

Takılı kalmanın üç başka yolu:

  • İşleyicinin içinde bir betik hatası done sebeleri. İşleyici durur ve oyuncu bekler. Konsolu okuyun. Bkz. reading a script error.
  • Hiçbir zaman yanıt vermeyen bir HTTP çağrısı. Bir zaman aşımı ekleyin, örneğin başlangıç saatini izleyerek ve hiçbir şey geri gelmezse bir ileti ile bitirerek.
  • done iki kez çağırmak, veya done sonrasında update çağırmak. Her sonlandırmadan sonra işleyiciyi bırakmak için return kullanın.

Aynı anda birkaç işleyici

Birçok kaynağı playerConnecting dinler ve her biri defer çağıran beklemeye ekler. Oyuncu yalnızca hepsinin bitmesi durumunda izin verilir. Bir scriptte yavaş veya bozuk bir işleyici herkesi tutuklar, bu nedenle bağlantılar takıldığında yalnızca bu kaynakla ilk olarak test edin.

Adaptive kartlar

deferrals.presentCard bir Adaptive Card'tan bir form veya kurallar ekranını gösterir, bu da bir JSON düzenidir. Oyuncu bir düğmeye basabilir ve geri çağrılması sonucu alır.

lua
local card = {
    type = 'AdaptiveCard',
    version = '1.3',
    body = {
        { type = 'TextBlock', text = 'Server rules', weight = 'Bolder', size = 'Large' },
        { type = 'TextBlock', text = 'Be respectful and no cheating.', wrap = true },
    },
    actions = {
        { type = 'Action.Submit', title = 'I agree', data = { accepted = true } },
    },
}

AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
    deferrals.defer()
    Wait(0)

    deferrals.presentCard(json.encode(card), function(data)
        if data and data.accepted then
            deferrals.done()
        else
            deferrals.done('You must accept the rules.')
        end
    end)
end)

Kartları basit tutun: metin, bir görüntü ve bir veya iki düğme. Geri çağrılması yine de done'da bitmelidir.

Kontrol listesi

Belirtisi Çözüm
Oyuncu bağlantıda takılı Bir yol asla deferrals.done çağırmaz; eksik else ekleyin
update veya done hiçbir etkiye sahip deferrals.defer() hemen sonrasında Wait(0) çağırın
Yanlış oyuncu etkilendi İlk olarak local src = source kaydedin
Kontrol bitmeden oyuncu izin verilir deferrals.defer() unuttunuz
Iletiyle reddetme deferrals.done('reason')
Oyuncuyu kabul etme deferrals.done() hiçbir argüman olmadan
Yalnızca birçok script ile asıl Başka bir kaynağın playerConnecting işleyicisi yavaş veya bozuk

Kısa yanıtlar

deferrals.defer() sonrasında neden Wait(0) gereklidir?

Erteleme yalnızca motor bir işaret ilerlediğinde etkindir. Aynı işarette deferrals.update veya deferrals.done'ı çağırmak göz ardı edilebilir, bu nedenle önce Wait(0) ile bir kez getirin.

Bir oyuncuyu nasıl reddederim?

Bir dize ile deferrals.done('your reason') çağırın. Oyuncu metni görür ve izin verilmez. deferrals.done() hiçbir argüman olmadan çağırmak bunları bağlanmasına izin verir.

deferrals.done() hiç çağırmazsam ne olur?

Oyuncu bağlantı zaman aşımına kadar bağlantı ekranında kalır. İşleyicideki her kod yolu deferrals.done ile bitmelidir.

Bu sorunu yaşatmayan scriptler

Tebex TemplateTebex mağazanız için kod gerektirmeyen premium tema; tamamen Tebex panelinden düzenlenir.Scripti gör →Mic PhoneTablete dönüşen katlanabilir bir telefon; oyuncunun gerçek telefonuna da taşınır.Scripti gör →

Okumaya devam edin