FiveM state bags: Entity(entity).state, GlobalState ve handlers

FiveM state bags nasıl çalışır: Entity(entity).state, Player(source).state, LocalPlayer.state, GlobalState, :set, change handlers ve olaylar yerine ne zaman tercih edilebilir

Sunucu ve her istemci arasında küçük bir veri parçası paylaşmak istiyorsunuz, örneğin bir aracın kilitli olması, bir oyuncunun kelepçeli olması veya mevcut hava durumu ve her değişiklikte olayları ateşleyen kodu yazmaya devam ediyorsunuz, sonra daha sonra bağlanan oyuncular için uyumlu olmaktan çıkıyor. State bags yerleşik cevaptır.

Bu makale, state bag türlerini, bunları yazma ve okuma, değişikliklere tepki verme ve bir olayın hala daha iyi bir seçim olduğu zamanı kapsar.

State bag nedir

State bag, bir şeye bağlı anahtarlar ve değerlerden oluşan tablo benzeri bir depo. Runtime bunu sizin için senkronize eder, değer ayarlandıktan sonra bağlanan oyuncuları da dahil ederek. FiveM size üç tür verir:

Bag Şu ile oku ve yaz Şu yerde yaşar
Bir entite Entity(entity).state Entite (ped, araç, obje)
Bir oyuncu Server'da Player(source).state, client'ta LocalPlayer.state Oyuncu
Sunucu GlobalState Tüm sunucu

Tüm bunlarda normal bir alan gibi bir değer okursunuz:

lua
local locked = Entity(vehicle).state.locked

Server'dan yazma

Server'da, bir değer ayarlamak bunu bu bag'i görebilen istemcilere çoğaltır:

lua
-- server
local veh = CreateVehicle(`adder`, 215.0, -810.0, 30.7, 90.0, true, true)
Entity(veh).state.locked = true

Player(source).state.cuffed = true

GlobalState.weather = 'RAIN'

Alan stilini veya aynı zamanda değerin çoğaltılıp çoğaltılmayacağını seçmenize izin veren açık çağrıyı kullanabilirsiniz:

lua
Entity(veh).state:set('locked', true, true)

:set(key, value, replicated) anahtarı, değeri ve bir boolean alır. true ile değer diğer tarafa gönderilir, false ile yazıldığı tarafta kalır.

İpucu: değerler sayılar, string'ler, boolean'lar ve tablolar olabilir. Bir tablo ayarladığınızda kopyalanır, bu nedenle okuduğunuz tablodaki bir alanı değiştirmek hiçbir şey yapmaz. Güncellemek için tüm tabloyu tekrar ayarlayın.

Client'tan yazma

Bir client, kendi oyuncusuna ve kontrol ettiği entitelere yazabilir, ancak düz atama yerel kalır:

lua
-- client
LocalPlayer.state:set('inService', true, true)  -- replicated to the server
LocalPlayer.state.hasMask = true                -- local only

Server bundan sonra Player(source).state.inService okuyabilir. Bunu güvenilmez olarak ele alın: değiştirilmiş bir client istediği herhangi bir değeri yazabilir. Client tarafından yazılan state'i kolaylık için (UI bayrakları gibi) kullanın ve avantajlı bağlanan herhangi bir şey (para, iş, izinler) server'da tutun.

GlobalState tam tersidir: server yazıyor, her client okuyor ve client'lar onu diğerleri için değiştiremez.

lua
-- client
local weather = GlobalState.weather

Değişikliklere tepki verme

Bir değeri döngüde yoklamak yerine, bir anahtar değiştiğinde çalışan bir handler kaydedin. Bu, state bags'ı client'ta kullanmanın ana nedenidir:

lua
-- AddStateBagChangeHandler(keyFilter, bagFilter, handler)
AddStateBagChangeHandler('locked', nil, function(bagName, key, value, reserved, replicated)
    local entity = GetEntityFromStateBagName(bagName)
    if entity == 0 then return end

    SetVehicleDoorsLocked(entity, value and 2 or 1)
end)
  • keyFilter umursadığınız anahtardır veya tüm anahtarlar için nil.
  • bagFilter bag'i sınırlandırır, örneğin belirli bir player bag'i veya tüm için nil.
  • bagName entity:1234, player:5 veya global gibi görünür. GetEntityFromStateBagName bir entity bag'i bir handle'a çevirir ve GetPlayerFromStateBagName bir player bag'i için aynısını yapar.

Client'ta, handler ateşlendiğinde entite henüz var olmayabilir, örneğin hala aktarılan bir araç için. GetEntityFromStateBagName bu durumda 0 döndürebilir, bu nedenle kontrol edin. Entite aktarıldığında state'i tekrar okumak güvenli bir alışkanlıktır.

Aynı fonksiyon server'da var olup, bir client tarafından çoğaltılan bir değer yazmasına tepki vermek için kullanışlıdır.

State bags veya olaylar

State bag kullanın Olay kullanın
Değer bir şeyin mevcut durumunu açıklar (kilitli, kelepçeli, görevde) Bir şey bir kez oldu (bir satın alma, bir isabet, bir düğmeye basma)
Daha sonra bağlanan oyuncular değeri görmeli Yalnızca şu anda mevcut oyuncuların bilmesi gerekiyor
Birçok oyuncu herhangi bir zaman onu okuyabilir Bir oyuncu bir şey söylenmelidir
Aksi takdirde döngüde yoklama yapardınız Bir sonuç veya tek seferlik yük geçirmeniz gerekiyor

İyi bir kural: olaylar eylemler için, state bags durum için. Birinin yarısından sonra bağlanan bir oyuncu aynı şeyi tekrar söylenirse, bu durumdur. Client ve server olayları diğer taraf için bkz.

Yaygın hatalar

  • Büyük veya hızlı değişen veriler için kullanmak. Her değişiklik ağ üzerinden gönderilir. Bir pozisyonu her frame'de state bag'e yazmayın.
  • Client yazılarını güvenmek. Client tarafından ayarladığı herhangi bir şeyi server'da hareket ettirmeden önce doğrulayın.
  • Handler'ın entite var olmadan önce çalışmasını bekleme. Handle'ı kontrol edin ve entite göründüğünde state'i tekrar okuyun.
  • Bir tabloyu yerinde mutate etme. state.items okuma, ekleme ve tekrar ayarlamama değişimi değişmez.
  • Reset'i unutmak. Bir entitedeki durum entiteyle gider, ancak player veya GlobalState üzerindeki durum bitene kadar kalır, bu nedenle işiniz bittiğinde onu nil olarak ayarlayın.
lua
Player(source).state.cuffed = nil

Kontrol listesi

Belirti Fix
Client bir değer ayarlar ama server onu asla görmez :set(key, value, true) kullanın böylece çoğaltılır
Handler çalışır ama entite handle'ı 0 Entite henüz aktarılmadı: kontrol edin ve daha sonra state'i tekrar okuyun
Geç katılanlar değeri kaçırırlar Olay yerine state bag kullanın
Tablo değişikliği senkronize olmaz Tüm tabloyu tekrar :set ile ayarlayın
Client'tan GlobalState değiştiremez Yalnızca server yazıyor: bir olay gönderin ve server'a ayarlamasını izin verin
İş bittiğinden sonra eski değer kalır Anahtarı nil olarak ayarlayın

Kısa yanıtlar

FiveM'de state bag nedir?

Bir entitiye, oyuncuya veya tüm sunucuya bağlı bir anahtar ve değer deposu. Ayarladığınız değerler oyun tarafından diğer tarafa senkronize edilir, bu nedenle her değişiklik için bir olay tetiklemeniz gerekmez.

Bir client, state bag'i değiştirebilir ve server onu görebilir mi?

Yalnızca değer çoğaltma açık olarak ayarlanırsa, örneğin LocalPlayer.state:set('key', value, true). Client'ta düz atama yerel kalır ve server bunu hiçbir önemli şey için asla güvenmemelidir.

State bags OneSync'e ihtiyaç duyar mı?

Entity state bags OneSync'e bağlıdır, mevcut sunucular varsayılan olarak kullanır. Player state ve GlobalState başlamak için daha kolay durumlardır.

Bu sorunu yaşatmayan scriptler

Parrots as PetsOmzunuzda duran, sizinle uçan ve çağırınca geri gelen on dört kuş.Scripti gör →Advanced BoostingTabletten araç boosting: D’den S+ sınıfına kontratlar, ekipler ve canlı sıra.Scripti gör →Hookah SystemYerleştirilebilir nargileler ve lounge mobilyaları; 50+ aroma ve efekt.Scripti gör →

Okumaya devam edin