Torebki stanu w FiveM: Entity(entity).state, GlobalState i handlery
Jak działają torebki stanu w FiveM: Entity(entity).state, Player(source).state, LocalPlayer.state, GlobalState, :set, handlery zmian i kiedy preferować je zamiast zdarzeń
Chcesz udostępnić małą część danych między serwerem a każdym klientem, na przykład że pojazd jest zablokowany, że gracz jest puta do kajdanek, lub bieżącą pogodę, a ciągle piszesz zdarzenia, które uruchamiają się przy każdej zmianie i tracą synchronizację dla graczy, którzy dołączają później. Torebki stanu są wbudowaną odpowiedzią.
Ten artykuł obejmuje typy torebek stanu, jak je pisać i czytać, jak reagować na zmiany i kiedy zdarzenie jest wciąż lepszym wyborem.
Co to jest torebka stanu
Torebka stanu to magazyn tabelaryczny kluczy i wartości dołączony do czegoś. Runtime synchronizuje go dla ciebie, łącznie z graczami, którzy połączą się po ustawieniu wartości. FiveM daje ci trzy rodzaje:
| Torebka | Czytaj i pisz za pomocą | Istnieje na |
|---|---|---|
| Encja | Entity(entity).state |
Encji (ped, pojazd, obiekt) |
| Gracz | Player(source).state na serwerze, LocalPlayer.state na kliencie |
Graczu |
| Serwer | GlobalState |
Całym serwerze |
We wszystkich z nich czytasz wartość jak normalne pole:
local locked = Entity(vehicle).state.lockedPisanie z serwera
Na serwerze ustawienie wartości replikuje ją do klientów, którzy widzą tę torebkę:
-- 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'Możesz użyć stylu pola lub jawnego wywołania, które również pozwala wybrać, czy wartość jest replikowana:
Entity(veh).state:set('locked', true, true):set(key, value, replicated) przyjmuje klucz, wartość i wartość logiczną. Z true wartość jest wysyłana na drugą stronę, z false pozostaje po stronie, która ją napisała.
Porada: wartości mogą być liczbami, stringami, wartościami logicznymi i tabelami. Tabela jest kopiowana podczas ustawiania, więc zmiana pola w tabeli, którą czytasz, nic nie robi. Ustaw całą tabelę ponownie, aby ją zaktualizować.
Pisanie z klienta
Klient może pisać do swojego własnego gracza i do encji, którymi steruje, ale zwykłe przypisanie pozostaje lokalne:
-- client
LocalPlayer.state:set('inService', true, true) -- replicated to the server
LocalPlayer.state.hasMask = true -- local onlySerwer może przeczytać Player(source).state.inService potem. Traktuj to jako niezaufane: zmodyfikowany klient może napisać dowolną wartość. Użyj stanu napisanego przez klienta dla wygody, takiej jak flagi interfejsu, i trzymaj wszystko z zaletą dołączoną (pieniądze, praca, uprawnienia) na serwerze.
GlobalState jest odwrotnie: serwer go pisze, każdy klient go czyta, a klienci nie mogą go zmieniać dla innych.
-- client
local weather = GlobalState.weatherReagowanie na zmiany
Zamiast sondować wartość w pętli, zarejestruj handler, który działa, gdy zmieni się klucz. To główny powód, aby używać torebek stanu na kliencie:
-- 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)keyFilterto klucz, na którym ci zależy, lubnildla każdego klucza.bagFilterogranicza torbę, na przykład konkretną torbę gracza, lubnildla wszystkich.bagNamewygląda jakentity:1234,player:5lubglobal.GetEntityFromStateBagNamezamienia torbę encji na handle, aGetPlayerFromStateBagNamerobi to samo dla torby gracza.
Na kliencie encja może jeszcze nie istnieć, gdy handler się uruchamia, na przykład dla pojazdu, który nadal przesyła. GetEntityFromStateBagName może w tym przypadku zwrócić 0, więc je sprawdź. Ponowne przeczytanie stanu, gdy encja przesyła, jest bezpiecznym nawykiem.
Ta sama funkcja istnieje na serwerze, gdzie jest przydatna do reagowania na pisanie przez klienta wartości replikowanej.
Torebki stanu lub zdarzenia
| Użyj torebki stanu, gdy | Użyj zdarzenia, gdy |
|---|---|
| Wartość opisuje aktualny stan czegoś (zablokowany, kajdanki, w służbie) | Coś się stało raz (zakup, trafienie, wciśnięcie przycisku) |
| Gracze, którzy dołączą później, muszą zobaczyć wartość | Tylko gracze obecni teraz muszą wiedzieć |
| Wielu graczy musi to czytać w dowolnym momencie | Jeden gracz musi być coś poinformowany |
| W innym przypadku sondowałbyś w pętli | Musisz przekazać wynik lub jednorazowy ładunek |
Dobra reguła: zdarzenia są dla akcji, torebki stanu są dla stanu. Jeśli gracz dołączający w połowie musiałby być poinformowany o tym samym ponownie, to jest stan. Przeczytaj zdarzenia klient i serwer aby dowiedzieć się więcej.
Częste błędy
- Używanie go do dużych lub szybko zmieniających się danych. Każda zmiana jest wysyłana przez sieć. Nie pisz pozycji do torebki stanu każdej ramki.
- Ufanie zapisu klienta. Zweryfikuj wszystko, co klient ustawił, zanim będziesz na tym działać na serwerze.
- Oczekiwanie, że handler uruchomi się przed istnieniem encji. Sprawdź handle i ponownie przeczytaj stan, gdy encja się pojawi.
- Mutowanie tabeli w miejscu. Przeczytanie
state.items, dodanie do niej i nieustaw ponownie nie zmienia nic. - Zapomnienie o resetowaniu. Stan na encji znika z encją, ale stan na graczu lub
GlobalStatepozostaje, aż go wyczyścisz, więc ustaw go nanil, gdy skończysz.
Player(source).state.cuffed = nilLista kontrolna
| Objaw | Naprawa |
|---|---|
| Klient ustawia wartość, ale serwer jej nigdy nie widzi | Użyj :set(key, value, true), aby była replikowana |
Handler uruchamia się, ale handle encji to 0 |
Encja nie jest jeszcze przesyłana: sprawdź i przeczytaj stan ponownie później |
| Spóźnieni dołączy chybią wartość | Użyj torebki stanu zamiast zdarzenia |
| Zmiana tabeli nie synchronizuje się | Ustaw całą tabelę ponownie za pomocą :set |
Nie można zmienić GlobalState z klienta |
Tylko serwer go pisze: wyślij zdarzenie i pozwól serwerowi to ustawić |
| Stara wartość pozostaje po zakończeniu pracy | Ustaw klucz na nil |
Szybkie odpowiedzi
Co to jest torebka stanu w FiveM?
Magazyn pary klucz-wartość dołączony do encji, gracza lub całego serwera. Wartości, które ustawisz, są synchronizowane między stronami przez grę, więc nie musisz uruchamiać zdarzenia dla każdej zmiany.
Czy klient może zmienić torebkę stanu i sprawić, że serwer to zobaczy?
Tylko jeśli wartość jest ustawiona z włączoną replikacją, na przykład LocalPlayer.state:set('key', value, true). Zwykłe przypisanie na kliencie pozostaje lokalne, a serwer nigdy nie powinien mu ufać w niczym, co ma znaczenie.
Czy torebki stanu potrzebują OneSync?
Torebki stanu encji zależą od OneSync, które obecne serwery domyślnie używają. Stan gracza i GlobalState są łatwiejszymi przypadkami, od których warto zacząć.
Skrypty bez tego problemu
Parrots as PetsCzternaście ptaków, które siedzą ci na ramieniu, latają z tobą i wracają na zawołanie.Zobacz skrypt →
Advanced BoostingBoosting pojazdów z tabletu: kontrakty od klasy D do S+, ekipy i kolejka na żywo.Zobacz skrypt →
Hookah SystemFajki wodne i meble lounge do rozstawienia, z ponad 50 smakami i efektami.Zobacz skrypt →