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:
local locked = Entity(vehicle).state.lockedServer'dan yazma
Server'da, bir değer ayarlamak bunu bu bag'i görebilen istemcilere çoğaltır:
-- 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:
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:
-- client
LocalPlayer.state:set('inService', true, true) -- replicated to the server
LocalPlayer.state.hasMask = true -- local onlyServer 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.
-- client
local weather = GlobalState.weatherDeğ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:
-- 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)keyFilterumursadığınız anahtardır veya tüm anahtarlar içinnil.bagFilterbag'i sınırlandırır, örneğin belirli bir player bag'i veya tüm içinnil.bagNameentity:1234,player:5veyaglobalgibi görünür.GetEntityFromStateBagNamebir entity bag'i bir handle'a çevirir veGetPlayerFromStateBagNamebir 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.itemsokuma, 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 onunilolarak ayarlayın.
Player(source).state.cuffed = nilKontrol 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.


