State Bags
Die gemeinsamen Zustandswerte, die ai-core und die ai-*-Skripte veröffentlichen - Spieler-Bags, Fahrzeug-Bags und GlobalState-Schlüssel - was jeder enthält, wer ihn schreibt und wie du ihn liest und ihm folgst.
Eine State Bag ist ein Wert, den FiveM für alle synchron hält: auf GlobalState (ein Wert für den ganzen Server), auf einem Spieler oder auf einer Entity (einem Fahrzeug). Jede Ressource auf jeder Seite kann ihn lesen, und er folgt Änderungen ohne ein eigenes Event. ai-core und die ai-*-Skripte nutzen sie für Zustand, den alle brauchen, nie für private Daten.
Nur lesen. Jeder Schlüssel unten hat eine Besitzer-Ressource, die als einzige ihn schreibt, immer vom Server aus. Schreibe diese Schlüssel nie selbst, weder vom Server noch vom Client: Der Besitzer würde dich überschreiben, und andere Skripte würden falschen Zustand sehen. Um den Zustand zu ändern, rufe den Export des Besitzers auf (zum Beispiel die Wiederbelebung von ai-death, den Dienst-Export von ai-core).
Wie du sie liest
Die Lib hat eine Klasse pro Art. Jede hält eine lokale Kopie, sodass get nichts kostet, und onChange führt deinen Listener nach einer Änderung aus.
| Art | TypeScript (Lib) | Lua |
|---|---|---|
| Ein GlobalState-Schlüssel | new GlobalKey(key, parse): .get(), .onChange((_, value, old) => ...) | GlobalState[key], AddStateBagChangeHandler(key, 'global', fn) |
| Viele GlobalState-Schlüssel mit einem Präfix | new GlobalGroup(prefix, parse): .get(id), .ids(), .onChange((id, value, old) => ...) | GlobalState[prefix .. id] |
| Die Bag eines Spielers | new PlayerState(key, parse): .get(serverId), .onChange((serverId, value, old) => ...) | Player(serverId).state[key], LocalPlayer.state[key] auf dem Client |
| Die Bag einer Entity | new EntityState(key, parse): .get(entity), .getByNetId(netId), .onChange((netId, value, old) => ...) | Entity(entity).state[key] |
parse prüft den Rohwert: stateNumber, stateBoolean, stateString aus der Lib oder deine eigene Funktion, die für einen schlechten Wert undefined zurückgibt. Alle kommen aus @aicore-fivem/lib/client oder @aicore-fivem/lib/server.
import { cache, GlobalKey, PlayerState, stateBoolean, stateNumber } from "@aicore-fivem/lib/client";
import { dutyCountKey, PLAYER_BAGS } from "@aicore-fivem/shared";
const policeOnDuty = new GlobalKey(dutyCountKey("police"), stateNumber);
const cuffed = new PlayerState(PLAYER_BAGS.cuffed, stateBoolean);
console.log(`police on duty: ${policeOnDuty.get() ?? 0}`);
policeOnDuty.onChange((_, count) => console.log(`police on duty now: ${count ?? 0}`));
cuffed.onChange((serverId, value) => {
if (serverId === cache.serverId) console.log(value ? "you are cuffed" : "you are free");
});Spieler-Bags (PLAYER_BAGS)
Schlüssel, die mehrere Ressourcen auf einem Spieler lesen. Konstante: PLAYER_BAGS in @aicore-fivem/shared.
| Schlüssel | Konstante | Besitzer | Wert |
|---|---|---|---|
dead | PLAYER_BAGS.dead | ai-death | true, solange der Spieler am Boden ist. Sonst fehlend oder false. Mit einem anderen Tod-Skript nutze stattdessen die Medizin-Ebene (Export IsDead, Lib medical): Andere Tod-Skripte nutzen eigene Schlüssel. |
cuffed | PLAYER_BAGS.cuffed | ai-police | true, solange der Spieler gefesselt ist. |
proximity | PLAYER_BAGS.proximity | ai-voice | Die Sprachreichweite in der Form von pma-voice: { index, distance, mode }. |
Fahrzeug-Bags (VEHICLE_BAGS)
Schlüssel auf Fahrzeug-Entities. Konstante: VEHICLE_BAGS in @aicore-fivem/shared.
| Schlüssel | Konstante | Besitzer | Wert |
|---|---|---|---|
ai:owned | VEHICLE_BAGS.owned | ai-vehicles | true auf einem gespawnten Fahrzeug mit Besitzer. |
ai:vid | VEHICLE_BAGS.id | ai-vehicles | Die ID des Fahrzeugs in ai-vehicles (Zahl). |
ai:props | VEHICLE_BAGS.props | ai-vehicles | Aussehen und Tuning des Fahrzeugs (VehicleProps). ai-core wendet es auf dem Client an, dem die Entity gehört. |
ai:setup | VEHICLE_BAGS.setup | ai-vehicles | Ein Spawn-Setup (VehicleSetup, zum Beispiel eine in einem Shop gewählte Farbe). ai-core wendet es einmal auf dem Besitzer-Client an. |
fuel | VEHICLE_BAGS.fuel | das Tank-Skript (ai-fuel; ai-core führt es für clientseitige Tank-Skripte) | Tankstand, 0-100. |
Um den Tankstand zu lesen, nutze die fuel-Ebene der Lib: Sie funktioniert mit jedem Tank-Skript, auch mit denen, die die Bag fuel nicht selbst schreiben.
GlobalState-Schlüssel von ai-core
| Schlüssel | Konstante | Wert |
|---|---|---|
ai:duty:<job> | dutyCountKey(job) (Präfix DUTY_COUNT_PREFIX) | Wie viele Spieler in diesem Job im Dienst sind (Zahl). Nur Anzahlen, nie wer. |
ai:interaction | CORE.interactionStateKey | "prompt" oder "target": wie Points der Lib Spieler interagieren lassen (Panel-Einstellung von ai-core). |
ai:pvp | CORE.pvpStateKey | true, wenn Spieler einander verletzen können (Panel-Einstellung pvp, Befehl /togglepvp). |
ai:inventory | INVENTORY_STATE_KEY | Ressourcenname des Inventars hinter der Inventar-Ebene von ai-core. Nicht gesetzt, solange keines läuft. |
ai:vehicleKeys | VEHICLE_KEYS_STATE_KEY | Ressourcenname des aktiven Fahrzeugschlüssel-Skripts. Nicht gesetzt, solange keines läuft. |
ai:appearance | APPEARANCE_STATE_KEY | Ressourcenname des aktiven Kleidungs-Skripts. Nicht gesetzt, solange keines läuft. |
ai:medical | CORE.medicalStateKey | Ressourcenname des aktiven Tod-Skripts. |
ai:mdt | CORE.mdtStateKey | Ressourcenname des aktiven MDT. |
ai:notify | CORE.notifyStateKey | Ressourcenname der Benachrichtigungs-UI, an die die Karten von ai-lib gehen. Nicht gesetzt: ai-lib zeichnet seine eigenen Karten. |
ai:fuel | FUEL_STATE_KEY | Ressourcenname des aktiven Tank-Skripts. Nicht gesetzt, solange keines läuft. |
ai:garages | GARAGES_STATE_KEY | Ressourcenname des aktiven Garagen-Skripts. Nicht gesetzt, solange keines läuft. |
Die Schlüssel mit Ressourcennamen sagen den Client-Hälften von ai-core, mit welchem Skript sie sprechen sollen. Lies sie, wenn du wissen musst, welches Skript läuft (für eine Log-Zeile, einen Hinweis an den Spieler), nicht um dieses Skript direkt aufzurufen: Rufe stattdessen die Ebene von ai-core auf.
import { GlobalKey, stateBoolean } from "@aicore-fivem/lib/server";
import { CORE } from "@aicore-fivem/shared";
const pvp = new GlobalKey(CORE.pvpStateKey, stateBoolean);
pvp.onChange((_, on) => console.log(on ? "PvP is on" : "PvP is off"));Schlüssel anderer ai-*-Skripte
Gemeinsamer Zustand, den einige ai-*-Skripte veröffentlichen, für Skripte, die mit ihnen arbeiten. Die Developer-Seite jedes Skripts hat die Details.
| Schlüssel | Wo | Besitzer | Wert |
|---|---|---|---|
door:<id> | GlobalState | ai-doorlock | true, solange die Tür abgeschlossen ist. |
ai:clock | GlobalState | ai-weathersync | { base, at, scale, frozen }: Spielminuten des Tages zur Serverzeit at (ms), die pro echter Minute um scale Spielminuten voranschreiten. Clients lassen die Uhr daraus selbst laufen. |
ai:weather | GlobalState | ai-weathersync | { type, blackout }: das aktuelle Wetter. |
ai:rweather:<id> | GlobalState | ai-weathersync | Das aktuelle Wetter einer Wetterregion. |
prop:<id> | GlobalState | ai-properties | true, wenn die Immobilie einen Besitzer hat. |
rob:<id> | GlobalState | ai-robberies | true, solange ein Überfallziel geleert ist und auf seinen Cooldown wartet. |
siren:lx | Fahrzeug | ai-sirens | Hauptsirenenton: 0 aus, 1-3 ein Ton. |
siren:manu | Fahrzeug | ai-sirens | Drucklufthorn / manuelle Sirene: 0 aus, 1 Horn, 2 manuell, 3 beides. |
siren:lightbar | Fahrzeug | ai-sirens | Das am Fahrzeug befestigte Lichtbalken-Modell; fehlt, wenn keines. |
UI-Events von ai-lib
Die Client-Events, die ai-lib auslöst, wenn ein Spieler ein Menü, einen Eingabedialog, eine Item-Auswahl, ein Minispiel oder eine Aufforderung beantwortet oder einen Fortschrittsbalken abbricht - für Skripte, die die Exports von ai-lib selbst aufrufen.
Events der Framework-Brücke
Die ESX-, QB- / Qbox- und vRP-Events, die ai-core auslöst, damit für diese Frameworks geschriebene Skripte weiter funktionieren, mit ihren genauen Argumenten, und die Framework-Events, die ai-core beantwortet.