FiveM olayları: RegisterNetEvent, TriggerServerEvent, TriggerClientEvent

FiveM istemci ve sunucu olayları nasıl çalışır: RegisterNetEvent, AddEventHandler, TriggerServerEvent, TriggerClientEvent -1 ile, source değişkeni ve olay adlandırması.

Oyun ve sunucu arasındaki çoğu betik hatası olaylara indirgenir: hiçbir zaman çalışmayan bir işleyici, kimseye gönderilmeyen bir olay veya yanlış oyuncuya işaret eden bir source.

Bu makale ağ olaylarının nasıl çalıştığını, her iki yönde nasıl kaydedilecekleri ve tetiklenecekleri ve iki betiğin hiçbir zaman çarpışmayacağı şekilde adlandırılması açıklar.

İki taraf

FiveM kaynağı istemci (oyuncu başına bir kopya) ve sunucu (bir kopya) üzerinde kod olabilir. Olaylar aracılığıyla konuşurlar:

From To Function
Client Server TriggerServerEvent
Server One client TriggerClientEvent(name, playerId, ...)
Server All clients TriggerClientEvent(name, -1, ...)
Same side Same side TriggerEvent

Argümanlar serileştirilir, bu nedenle sayılar, dizeler, boolean'lar ve tablolar gönderebilirsiniz. İşlevleri gönderemezsiniz. Varlık tutamaçları her makineye yereldir, bu nedenle bunun yerine bir ağ kimliği (NetworkGetNetworkIdFromEntity) gönderin.

İşleyici kaydetme

İşleyici, olay geldiğinde çalışan bir işlevdir. Ağdan gelen bir olay için bunu da izin verilen olarak işaretlemeniz gerekir:

lua
RegisterNetEvent('my_script:client:notify', function(message)
    print(message)
end)

Kısa form bu: RegisterNetEvent işlevi ikinci argüman olarak olayı kaydeder ve işleyiciyi ekler. Uzun form aynı iki adımda yapar:

lua
RegisterNetEvent('my_script:client:notify')
AddEventHandler('my_script:client:notify', function(message)
    print(message)
end)

Yalnızca AddEventHandler kullanırsanız, işleyici yerel TriggerEvent çağrıları için çalışır, ancak diğer taraftan TriggerServerEvent veya TriggerClientEvent görmezden gelinir. Bu, hiçbir şey yapmayan bir olayın en yaygın nedenidir.

İstemciden sunucuya

lua
-- client
TriggerServerEvent('my_script:server:buy', 'water', 2)
lua
-- server
RegisterNetEvent('my_script:server:buy', function(item, amount)
    local src = source
    print(('player %s wants %s x %s'):format(src, amount, item))
end)

Sunucuda, global source olayı tetikleyen oyuncunun kimliğini tutar. İstemci bunu göndermez, bu nedenle argümanlarını değiştiren bir istemci tarafından sahte yapılamaz.

Sunucudan istemciye

lua
-- server: to one player
TriggerClientEvent('my_script:client:notify', src, 'Purchase done')

-- server: to everyone
TriggerClientEvent('my_script:client:notify', -1, 'Server restart in 5 minutes')
lua
-- client
RegisterNetEvent('my_script:client:notify', function(message)
    print(message)
end)

TriggerClientEvent ikinci argümanı her zaman hedeftir. Unutursanız, ilk veri argümanınız oyuncu kimliği olarak okunur ve olay hiç yere gitmez.

Beklemeden önce source'u kaydedin

source sahip olduğunuz bir değer değildir, çalışan olay için runtime'ın ayarladığı globaldir. İşleyiciniz Wait çağırırsa veya MySQL.query.await gibi getiri veren bir şey çağırırsa, bu arada başka olay çalışabilir ve source değişir.

lua
RegisterNetEvent('my_script:server:buy', function(item, amount)
    local src = source            -- copy it first

    Wait(500)                     -- or any await
    print(src)                    -- still the right player
    print(source)                 -- may be someone else now
end)

Her sunucu işleyicisinin ilk satırı local src = source yapın ve bundan sonra src kullanın. Aynı şey, bir işleve ilettiğiniz geri çağırı içinde de geçerlidir.

Olayları adlandırma

Olaylar tüm sunucuya globaldir: herhangi bir kaynak herhangi bir olay adını tetikleyebilir. İki betik de buy veya server:buy kaydederse, her iki işleyici de çalışır ve oyuncu ada göre tetikleyebilir.

Her olayın ön eki kaynağı ve tarafı:

lua
'my_script:server:buy'
'my_script:client:updateJob'

Diğer betiklerin olay adlarını yeniden kullanmayın ve olayınızı giveMoney gibi genel bir ad vermeyin. Okunabilir bir ad da konsolda hangi betiğin ne gönderdiğini açık yapar.

İstemciye asla güvenmeyin

TriggerServerEvent aracılığıyla gelen her şey bir hileci tarafından herhangi bir argümanla, herhangi bir zamanda tetiklenebilir. Sunucuda kontrol edin:

  • oyuncunun bunu yapmasına izin verileceğini (iş, mesafe, soğuma),
  • tutarlar ve öğe adlarının geçerli olduğunu,
  • asla argümanlardan fiyat veya ödül almadığını.
lua
RegisterNetEvent('my_script:server:buy', function(item, amount)
    local src = source
    if type(amount) ~= 'number' or amount < 1 or amount > 10 then return end
    -- look the price up on the server, do not read it from the client
end)

Tam liste sunucu olaylarını güvenli hale getirme kısmında. Arayanın geri dönmesi gereken sonuç için geri çağırı iki olaydan daha temiz: bkz. ESX, QBCore ve ox_lib'deki sunucu geri çağırıları.

Büyük veya sık olaylar

Her olay bir ağ mesajıdır. Her karede birini tetiklemeyín ve tüm oyunculara çok büyük bir tablo göndermeyín. Sunucu konsolu güvenilir olaylar taştığında söylerse, çok fazla, çok hızlı gönderiyorsunuz: bkz. güvenilir ağ olay taşması.

Kontrol Listesi

Belirtisi Düzeltme
İşleyici diğer taraftan hiçbir zaman çalışmaz Yalnızca AddEventHandler değil RegisterNetEvent kullanın
TriggerClientEvent kimseye ulaşmaz İkinci argüman olarak oyuncu kimliği veya -1 geçirin
source nil veya yanlış oyuncu local src = source ilk satır, herhangi Wait den önce
İki betik aynı olaya tepki verir Adları kaynağıyla önek verin: my_script:server:buy
İstemci kendisine öğe veya para verebilir Sunucuda doğrulayın ve fiyatları orada arayın
Konsol veya gecikme olay spam'ı Daha az, daha az sıklıkla gönderin: güvenilir ağ olay taşması bakın

Kısa yanıtlar

RegisterNetEvent ile AddEventHandler arasındaki fark nedir?

RegisterNetEvent olayın ağın diğer tarafından tetiklenmesine izin verir. AddEventHandler sadece bir işlev ekler. Ağ olayı için bir işleyici her ikisine de ihtiyaç duyar veya işlevi ikinci argüman olarak RegisterNetEvent ile.

Her oyuncuya bir olay nasıl gönderilir?

Sunucuda, TriggerClientEvent('my_script:client:thing', -1, data). -1 tüm bağlı istemciler anlamına gelir.

Sunucu olayımda kaynak neden yanlış?

source geçerli olayı tetikleyen oyuncuyu tutan globaldir. Wait çağırırsanız ve bu arada başka olay çalışırsa değişir. Önce yerel olarak kopyalayın: local src = source.

Bu sorunu yaşatmayan scriptler

Advanced BoostingTabletten araç boosting: D’den S+ sınıfına kontratlar, ekipler ve canlı sıra.Scripti gör →Drug Dealer Applb-phone uygulaması olarak sokak satışı: bölgeler, NPC alıcılar, seviyeler ve polis ihbarları.Scripti gör →Shop CreatorBir dakikadan kısa sürede dükkân kurun — sahipler, çalışanlar, kasalar ve soygunlar dahil.Scripti gör →

Okumaya devam edin