State bagi
EntityState, PlayerState, GlobalKey, GlobalGroup i parsery stateNumber, stateBoolean, stateString: odczyt replikowanych wartości z pamięci.
State bag to wartość, którą FiveM kopiuje z serwera do klientów, które jej potrzebują: paliwo pojazdu (Entity(vehicle).state.fuel), czy gracz leży (Player(id).state.dead), flaga dla całego serwera (GlobalState["ai:pvp"]).
Bezpośredni odczyt bagu jest wolny: każdy odczyt buduje proxy, wywołuje kilka natywek i ponownie dekoduje wartość. Te klasy trzymają jeden handler zmian na klucz i kopię każdej wartości w pamięci, więc odczyt to wyszukanie w mapie. Używaj ich dla każdego bagu, który czytasz więcej niż raz.
import { EntityState, PlayerState, GlobalKey, GlobalGroup, stateNumber, stateBoolean, stateString } from "@aicore-fivem/lib/client";import { EntityState, PlayerState, GlobalKey, GlobalGroup, stateNumber, stateBoolean, stateString } from "@aicore-fivem/lib/server";Klas nie ma w @aicore-fivem/lib/fivem: importuj je z wejścia klienta albo serwera. Tylko serwer zapisuje state bagi (sv_stateBagStrictMode); klient prosi serwer przez callback, a serwer ustawia wartość. Metody set serwera są na stronie Lib: serwer, State bagi.
Lua: żadna z nich nie ma odpowiednika w Lua. Lua sam czyta bagi (Entity(vehicle).state.fuel, Player(id).state.dead, GlobalState['ai:pvp']) i nasłuchuje przez AddStateBagChangeHandler.
Klucze używane przez ai-core i skrypty ai-* są wymienione na stronie Zdarzenia i stan.
Parsery
Każda klasa przyjmuje parser: funkcję, która zamienia surową replikowaną wartość w twój typ albo zwraca undefined, gdy wartość jest nieprawidłowa. Typ to StateParse<T> = (value: unknown) => T | undefined. Wyczyszczony bag (null) jest zawsze czytany jako undefined; parser nigdy go nie widzi.
stateNumber
Przyjmuje skończoną liczbę; wszystko inne (tekst, NaN, Infinity) czyta jako undefined.
Strona: Klient i serwer · Czeka: nie
stateNumber: StateParse<number>Przykład
import { EntityState, stateNumber } from "@aicore-fivem/lib/client";
const fuel = new EntityState("fuel", stateNumber); // 0-100, ustawiane przez skrypt paliwastateBoolean
Przyjmuje true albo false; wszystko inne czyta jako undefined.
Strona: Klient i serwer · Czeka: nie
stateBoolean: StateParse<boolean>Przykład
import { PlayerState, stateBoolean } from "@aicore-fivem/lib/client";
const dead = new PlayerState("dead", stateBoolean); // true, gdy gracz leży (ai-death)stateString
Przyjmuje string; wszystko inne czyta jako undefined.
Strona: Klient i serwer · Czeka: nie
stateString: StateParse<string>Przykład
import { GlobalKey, stateString } from "@aicore-fivem/lib/client";
const inventoryScript = new GlobalKey("ai:inventory", stateString); // nazwa zasobu aktywnego ekwipunkuDla wartości będącej obiektem napisz własny parser, który sprawdza każde pole i zwraca undefined dla złej wartości:
import { PlayerState, type StateParse } from "@aicore-fivem/lib/client";
type Proximity = { index: number; distance: number; mode: string };
const proximity: StateParse<Proximity> = (v) => {
if (typeof v !== "object" || v === null) return undefined;
const { index, distance, mode } = v as Record<string, unknown>;
return typeof index === "number" && typeof distance === "number" && typeof mode === "string"
? { index, distance, mode }
: undefined;
};
const voiceRange = new PlayerState("proximity", proximity); // zasięg pma-voice, zapisywany przez ai-voiceKlasy
EntityState
Jeden klucz state bagów encji (fuel, ai:owned...), dla każdej encji sieciowej. Wartości są trzymane według id sieciowego; odczyt przyjmuje uchwyt encji.
Strona: Klient i serwer · Czeka: nie
new EntityState<T>(key: string, parse: StateParse<T>)Parametry
Prop
Type
Metody
Prop
Type
Przykład
import { EntityState, stateNumber, cache, every } from "@aicore-fivem/lib/client";
const fuel = new EntityState("fuel", stateNumber);
every(1000, () => {
if (cache.vehicle === false) return;
SendNUIMessage({ action: "fuel", value: fuel.get(cache.vehicle) ?? 100 });
});Pamięć sama pozostaje mała: serwer zapomina encję, gdy zostanie usunięta, a klient co 30 sekund porzuca encje, które opuściły jego zasięg. Id sieciowe użyte ponownie przez nową encję jest czytane od nowa.
PlayerState
Jeden klucz state bagów gracza (dead, cuffed, proximity z pma-voice...), według id serwerowego.
Strona: Klient i serwer · Czeka: nie
new PlayerState<T>(key: string, parse: StateParse<T>)Parametry
Prop
Type
Metody
Prop
Type
Przykład
import { PlayerState, stateBoolean, onClientCallback } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
const dead = new PlayerState("dead", stateBoolean);
const cuffed = new PlayerState("cuffed", stateBoolean);
onClientCallback("my-shop:open", (source) => {
if (dead.get(source) || cuffed.get(source)) return fail("CANNOT_NOW");
return { ok: true };
});Na serwerze gracz, który wychodzi, jest zapominany w każdym PlayerState twojego zasobu (jeden wspólny listener playerDropped).
GlobalKey
Jeden klucz GlobalState: wartość, której potrzebuje każdy gracz (przełącznik PvP, aktywny ekwipunek). Czytana raz przy starcie, potem utrzymywana aktualną przez swój handler zmian.
Strona: Klient i serwer · Czeka: nie
new GlobalKey<T>(key: string, parse: StateParse<T>)Parametry
Prop
Type
Metody
Prop
Type
Przykład
import { GlobalKey, stateBoolean } from "@aicore-fivem/lib/client";
const pvp = new GlobalKey("ai:pvp", stateBoolean);
pvp.onChange((_id, on) => SendNUIMessage({ action: "pvp", value: on === true }));GlobalGroup
Wiele kluczy GlobalState o wspólnym prefiksie (ai:duty:police, ai:duty:ambulance), czytanych według części po prefiksie. Wszystkie grupy zasobu dzielą jeden handler.
Strona: Klient i serwer · Czeka: nie
new GlobalGroup<T>(prefix: string, parse: StateParse<T>)Parametry
Prop
Type
Metody
Prop
Type
Przykład
ai-core publikuje, ilu graczy jest na służbie w każdej pracy, pod ai:duty:<job>:
import { GlobalGroup, stateNumber } from "@aicore-fivem/lib/client";
const onDuty = new GlobalGroup("ai:duty:", stateNumber);
function policeOnline(): number {
return onDuty.get("police") ?? 0;
}Twórz każdą klasę raz na klucz, na górze pliku, nigdy wewnątrz funkcji, która działa często: każda instancja dodaje handler zmian. GlobalState jest wysyłany do każdego gracza, więc umieszczaj tam tylko wartości, których potrzebuje każdy gracz.
Harmonogram i cykl życia
every, onStop, caller, ByResource, Reasons, sleep i waitFor: praca okresowa, czekanie i dane należące do zasobu, który je zarejestrował.
Akcje i wejście z klienta
fail, isActionOk, replyError i ścisłe czytniki readInt, readFinite, readId, readText, readVec3, readVec4, oneArg, asArgs, isRecord.