AI Core
API-ReferenzLib: Client

Mitgliedschaft und Spielerdaten

hasJob, inGang, onDutyIn, allows, onMembershipChange, getPlayerData, onPlayerData und seedPlayerData - Charakter, Geld, Jobs, Dienst und Gangs des lokalen Spielers, wie ai-core sie schickt.

ai-core schickt die eigenen Daten des lokalen Spielers an seinen Client: einen Snapshot, wenn der Charakter lädt, danach nur die Werte, die sich ändern. Diese Helfer lesen diese Kopie, daher kostet eine Prüfung einen Speicherzugriff und fragt nie den Server.

Nutze sie für das, was der Spieler sieht (das canShow eines Punkts, ein Radialeintrag, eine Menüzeile). Der Server entscheidet mit denselben Daten, was der Spieler tun darf (online auf Spieler und Charaktere): Eine Client-Prüfung ist nie ein Beweis.

Spielerdaten

Die Werte, die ai-core hält, nach Schlüssel (AiPlayerData):

Prop

Type

Die Mitgliedstypen sind CharacterInfo, JobMembership und GangMembership.

getPlayerData

Der letzte Wert eines Schlüssels. Beim ersten Gebrauch in deiner Ressource liest es auch alles, was ai-core schon geschickt hat (aus dem Export GetPlayerData von ai-core), sodass eine Ressource, die nach dem Laden des Spielers neu gestartet wurde, die Werte sofort hat.

Seite: Client · Wartet: nein

Signatur
getPlayerData<K extends keyof AiPlayerData>(key: K): AiPlayerData[K] | undefined
Lua
local value = aiLib.playerData.get(key)

Parameter

Prop

Type

Rückgabewert

AiPlayerData[K] | undefined: der Wert, oder undefined (nil in Lua), wenn noch nichts angekommen ist (kein Charakter geladen, ai-core nicht gestartet).

Beispiel

import { getPlayerData, notify } from "@aicore-fivem/lib/client";

RegisterCommand(
  "whoami",
  () => {
    const character = getPlayerData("character");
    const job = getPlayerData("job");
    const cash = getPlayerData("money")?.cash ?? 0;
    if (!character) return notify("No character loaded", "error");
    notify(`${job?.job ?? "unemployed"} (${job?.grade ?? 0}), $${cash}`, "info");
  },
  false,
);

onPlayerData

Führt jedes Mal einen Handler aus, wenn ai-core einen Schlüssel für diesen Spieler schickt.

Seite: Client · Wartet: nein

Signatur
onPlayerData<K extends keyof AiPlayerData>(key: K, handler: (value: AiPlayerData[K]) => void): () => void
Lua
aiLib.playerData.onChange(key, function(value) end)

Parameter

Prop

Type

Rückgabewert

TypeScript: () => void, eine Funktion, die den Handler entfernt. Lua gibt nichts zurück.

Beispiel

import { onPlayerData } from "@aicore-fivem/lib/client";

const stop = onPlayerData("money", (money) => {
  SendNUIMessage({ action: "money", data: { cash: money.cash ?? 0, bank: money.bank ?? 0 } });
});
// stop(), wenn das HUD endgültig schließt

Werte, die vor dem Start deiner Ressource geschickt wurden, werden für den Handler nicht erneut abgespielt. Lies den aktuellen Wert einmal mit getPlayerData beim Start und folge danach Änderungen mit onPlayerData.

seedPlayerData

Füllt Werte von Hand. Schlüssel, die schon einen Wert haben, bleiben erhalten. Du brauchst es nicht: Die Lib befüllt sich beim ersten Gebrauch selbst aus ai-core.

Seite: Client · Wartet: nein

Signatur
seedPlayerData(data: Partial<AiPlayerData>): void

Kein Lua-Zwilling.

Parameter

Prop

Type

Rückgabewert

void.

Beispiel

import { seedPlayerData } from "@aicore-fivem/lib/client";

// Eine Testumgebung ohne ai-core.
seedPlayerData({ jobs: [{ job: "police", grade: 3 }], duty: "police" });

Mitgliedschaftsprüfungen

hasJob

Ob der Spieler einen der Jobs mit einem Mindestrang hat, im Dienst oder nicht.

Seite: Client · Wartet: nein

Signatur
hasJob(jobs: readonly string[], minGrade?: number): boolean

Kein Lua-Zwilling: Gehe aiLib.playerData.get('jobs') durch (siehe das Lua-Beispiel bei points.add).

Parameter

Prop

Type

Rückgabewert

boolean: true, wenn die Liste leer ist oder der Spieler einen der jobs mit minGrade oder höher hat.

Beispiel

import { hasJob, onMembershipChange, Points } from "@aicore-fivem/lib/client";

const points = new Points();
points.add("armory", {
  coords: { x: 482.6, y: -995.2, z: 30.7 },
  label: "Armory",
  canShow: () => hasJob(["police", "sheriff"], 1),
  onPressed: () => emitNet("mypolice:armory"),
});
onMembershipChange(() => points.refresh());

inGang

Ob der Spieler in einer der Gangs mit einem Mindestrang ist.

Seite: Client · Wartet: nein

Signatur
inGang(gangs: readonly string[], minGrade?: number): boolean

Kein Lua-Zwilling: Gehe aiLib.playerData.get('gangs') durch.

Parameter

Prop

Type

Rückgabewert

boolean: true, wenn die Liste leer ist oder der Spieler in einer der gangs mit minGrade oder höher ist.

Beispiel

import { inGang, radial } from "@aicore-fivem/lib/client";

radial.add({
  id: "mygang:stash",
  label: "Gang stash",
  icon: "box",
  canShow: () => inGang(["ballas", "vagos"], 2),
  onPressed: () => emitNet("mygang:stash"),
});

onDutyIn

Ob der Spieler in einem der Jobs im Dienst ist.

Seite: Client · Wartet: nein

Signatur
onDutyIn(jobs: readonly string[]): boolean

Kein Lua-Zwilling: aiLib.playerData.get('duty') ist der Job im Dienst.

Parameter

Prop

Type

Rückgabewert

boolean: true, wenn der Dienst-Job des Spielers in jobs ist.

Beispiel

import { onDutyIn, Points } from "@aicore-fivem/lib/client";

const points = new Points();
points.addVehicle("mymech:repair", {
  label: "Repair",
  icon: "wrench",
  canShow: () => onDutyIn(["mechanic"]),
  onPressed: (vehicle) => emitNet("mymech:repair", NetworkGetNetworkIdFromEntity(vehicle)),
});

onMembershipChange

Führt eine Funktion aus, wenn sich die Jobs, der Dienst oder die Gangs des Spielers ändern. Nutze es, um Punkte und Blips zu aktualisieren, deren canShow sie liest.

Seite: Client · Wartet: nein

Signatur
onMembershipChange(fn: () => void): void

Kein Lua-Zwilling: aiLib.playerData.onChange für jobs, duty und gangs.

Parameter

Prop

Type

Rückgabewert

void.

Beispiel

import { onMembershipChange, Points, radial } from "@aicore-fivem/lib/client";

const points = new Points();
onMembershipChange(() => {
  points.refresh();
  radial.refresh();
});

allows

Ob der lokale Spieler einen Ort mit einer Zugriffsregel nutzen darf. online.allows(source, rule) auf dem Server entscheidet mit derselben Regel, sodass der Spieler genau das sieht, was der Server ihn nutzen lässt. Lies die Regel aus einem Panel-Eintrag mit readAccess(record) (@aicore-fivem/lib/shared).

Seite: Client · Wartet: nein

Signatur
allows(rule: AccessRule): boolean

Kein Lua-Zwilling.

Parameter

Prop

Type

AccessRule

Prop

Type

Der Typ ist AccessRule.

Rückgabewert

boolean: true, wenn beide Listen leer sind (alle); wenn der Spieler in einer der gangs mit deren Mindestrang ist; oder wenn der Spieler einen der jobs mit dessen Mindestrang hat (und darin im Dienst ist, wenn onDuty). Sonst false.

Beispiel

resource/client/index.ts
import { AdminWorld, allows, callAction, onMembershipChange, Points } from "@aicore-fivem/lib/client";
import { readAccess, readVec3, RecordObjects, type AccessRule } from "@aicore-fivem/lib/shared";

const world = new AdminWorld(["stashes"]);
const points = new Points();

interface Stash { coords: { x: number; y: number; z: number }; access: AccessRule }
const readStash = (_key: string, raw: Record<string, unknown>): Stash | null => {
  const coords = readVec3(raw.coords);
  return coords ? { coords, access: readAccess(raw) } : null;
};

new RecordObjects(world, "stashes", readStash, (id, stash) => {
  points.add(id, {
    coords: stash.coords,
    label: "Stash",
    canShow: () => allows(stash.access),
    onPressed: () => callAction("mystash:open", [id], { fallback: "STASH_FAILED" }),
  });
  return () => points.remove(id);
});

onMembershipChange(() => points.refresh());

Auf dieser Seite