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.
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ı
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)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.Wait(0)defer()hemen sonrasında gereklidir.deferile aynı işaretteupdate,doneveyapresentCardçağrıları çalışmayabilir.deferrals.update(message)oyuncunun bağlantı ekranında gördüğü metni değiştirir. İlerleme göstermek için kullanın.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.Waitveya HTTP isteğinden sonra, genelsourcebaşka bir oyuncuyu işaret edebilir.
Oyuncu reddetme
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.
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.
-- 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:
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ı
donesebeleri. İş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.
doneiki kez çağırmak, veyadonesonrasındaupdateçağırmak. Her sonlandırmadan sonra işleyiciyi bırakmak içinreturnkullanı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.
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.

