AI Core
API-ReferenzLib: Shared und fivem

Aktionen und Client-Eingaben

fail, isActionOk, replyError und die strikten Leser readInt, readFinite, readId, readText, readVec3, readVec4, oneArg, asArgs, isRecord.

Alles, was ein Client sendet, kann ein Cheater fälschen: ein negativer Betrag, ein Bruch, wo du eine ganze Zahl erwartest, ein String mit 10 MB, ein Objekt statt einer Zahl. Die strikten Leser auf dieser Seite machen aus einem rohen Wert einen geprüften Wert, oder null, um ihn abzulehnen. Sie ersetzen einen fehlerhaften Wert nie durch einen Standardwert (das tun die Leser für Panel-Daten, für Dateien, die der Serverbetreiber bearbeitet).

Jede Server-Aktion antwortet mit einem ActionResult: { ok: true } oder einer Ablehnung mit einem Sprachschlüssel.

TypeScript
import { fail, isActionOk, replyError, readInt, readFinite, readId, readText, readVec3, readVec4, oneArg, asArgs, isRecord } from "@aicore-fivem/lib/shared";

Wohin die Leser gehören: in die Option args von onClientCallback und onClientEvent (siehe Client-Eingaben). Der Parser bekommt die rohen Argumente als Array und gibt die geprüften als Array zurück, oder null, um den Aufruf abzulehnen, bevor dein Handler läuft.

Aktionsergebnisse

fail

Baut eine Ablehnung: { ok: false, error }. Gib sie aus einem Aktions-Handler zurück; callAction auf dem Client zeigt den übersetzten Text von error als Fehlerbenachrichtigung an.

Seite: Client, Server und NUI · Wartet: nein

Signatur
fail(error: string): { ok: false; error: string }
Lua
return aiLib.fail('NOT_ENOUGH_MONEY') -- { ok = false, error = 'NOT_ENOUGH_MONEY' }

Parameter

Prop

Type

Rückgabewert

{ ok: false, error: string }, was zu jedem ActionResult passt.

Beispiel

resource/server/index.ts
import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
import { fail, oneArg, readInt, type ActionResult } from "@aicore-fivem/lib/shared";

const core = resourceExport("ai-core");

onClientCallback(
  "my-shop:buyWater",
  { args: oneArg((v) => readInt(v, 1, 10)), lock: true },
  (source, count): ActionResult => {
    if (!core.CanCarryItem(source, "water", count)) return fail("NO_SPACE");
    if (!core.RemoveMoney(source, "cash", count * 5, "Water")) return fail("NOT_ENOUGH_MONEY");
    core.AddItem(source, "water", count);
    return { ok: true };
  },
);

Auf dem Client zeigt callAction("my-shop:buyWater", [2], { fallback: "BUY_FAILED" }) (Lua aiLib.callAction) die Ablehnung für dich an. Siehe Mit dem Server sprechen.

isActionOk

Prüft, ob eine Antwort ein erfolgreiches ActionResult ist (ok === true). Nutze es, wenn du eine Antwort von Hand liest statt mit callAction.

Seite: Client, Server und NUI · Wartet: nein

Signatur
isActionOk(reply: unknown): reply is { ok: true } & Record<string, unknown>

Lua: kein Zwilling; prüfe type(reply) == 'table' and reply.ok == true.

Parameter

Prop

Type

Rückgabewert

true, wenn reply ein Objekt mit ok: true ist. Die zusätzlichen Felder werden nicht geprüft: Parse die, die du liest.

Beispiel

resource/client/index.ts
import { triggerServerCallback } from "@aicore-fivem/lib/client";
import { isActionOk, readId } from "@aicore-fivem/lib/shared";

/** Asks the server to create a garage; answers its new id, or null. */
async function createGarage(name: string): Promise<number | null> {
  const reply = await triggerServerCallback("my-garage:create", [name]).catch(() => null);
  if (!isActionOk(reply)) return null;
  return readId(reply.id); // ein zusätzliches Feld: prüfen wie jede andere Eingabe
}

replyError

Der Sprachschlüssel einer abgelehnten Antwort: ihr error, oder fallback, wenn die Antwort fehlt oder fehlerhaft ist. null, wenn die Antwort ok ist.

Seite: Client, Server und NUI · Wartet: nein

Signatur
replyError(reply: unknown, fallback: string): string | null

Lua: kein Zwilling.

Parameter

Prop

Type

Rückgabewert

null bei einer ok-Antwort. Sonst das error der Antwort, wenn es ein nicht leerer String ist, sonst fallback.

Beispiel

resource/client/index.ts
import { triggerServerCallback, notify, loadLocaleTexts } from "@aicore-fivem/lib/client";
import { replyError } from "@aicore-fivem/lib/shared";

const texts = loadLocaleTexts();

async function buyWater(): Promise<boolean> {
  const reply = await triggerServerCallback("my-shop:buy", ["water"]).catch(() => null);
  const error = replyError(reply, "BUY_FAILED");
  if (error !== null) notify(texts[error] ?? error, "error");
  return error === null;
}

Strikte Leser

readFinite

Eine endliche Zahl, sonst null. NaN, Infinity, Text und alles andere werden abgelehnt.

Seite: Client, Server und NUI · Wartet: nein

Signatur
readFinite(value: unknown): number | null

Lua: kein Zwilling; prüfe type(value) == 'number' and value == value and value ~= math.huge and value ~= -math.huge.

Parameter

Prop

Type

Rückgabewert

Die Zahl, oder null.

Beispiel

import { readFinite } from "@aicore-fivem/lib/shared";

readFinite(12.5);     // 12.5
readFinite(NaN);      // null
readFinite("12");     // null

readInt

Eine ganze Zahl zwischen min und max (beide eingeschlossen), sonst null. Brüche, NaN, Infinity, Text und Werte außerhalb des Bereichs werden abgelehnt. Nutze es für Anzahlen, Beträge, Slots, Indizes.

Seite: Client, Server und NUI · Wartet: nein

Signatur
readInt(value: unknown, min: number, max: number): number | null

Lua: kein Zwilling; prüfe math.type(value) == 'integer' and value >= min and value <= max.

Parameter

Prop

Type

Rückgabewert

Die Zahl, oder null.

Beispiel

resource/server/index.ts
import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
import { fail, readInt, readText } from "@aicore-fivem/lib/shared";

const core = resourceExport("ai-core");
const prices = new Map<string, number>([["water", 5], ["bread", 3]]);

onClientCallback(
  "my-shop:buy",
  {
    args: ([rawItem, rawCount]) => {
      const item = readText(rawItem, 64);
      const count = readInt(rawCount, 1, 50);
      return item !== null && count !== null ? [item, count] : null;
    },
    lock: true,
  },
  (source, item, count) => {
    const price = prices.get(item); // nur Items, die dieser Shop verkauft
    if (price === undefined) return fail("UNKNOWN_ITEM");
    if (!core.CanCarryItem(source, item, count)) return fail("NO_SPACE");
    if (!core.RemoveMoney(source, "cash", price * count, "Shop")) return fail("NOT_ENOUGH_MONEY");
    core.AddItem(source, item, count);
    return { ok: true };
  },
);

readId

Eine positive 32-Bit-Ganzzahl (1 bis 2.147.483.647), sonst null. Nutze es für Eintrags-IDs, Tokens und Netzwerk-IDs, die ein Client sendet.

Seite: Client, Server und NUI · Wartet: nein

Signatur
readId(value: unknown): number | null

Lua: kein Zwilling; prüfe math.type(value) == 'integer' and value > 0 and value <= 2147483647.

Parameter

Prop

Type

Rückgabewert

Die ID, oder null.

Beispiel

resource/server/index.ts
import { onClientCallback, vehicleFromNet } from "@aicore-fivem/lib/server";
import { oneArg, readId, fail } from "@aicore-fivem/lib/shared";

onClientCallback("my-tow:attach", { args: oneArg(readId) }, (source, netId) => {
  const vehicle = vehicleFromNet(netId);
  if (vehicle === 0) return fail("NO_VEHICLE");
  return { ok: true };
});

Eine gültige ID ist kein gültiges Ziel. Prüfe immer, dass der Eintrag oder die Entity existiert, dass der Spieler sie nutzen darf und dass er in ihrer Nähe ist.

readText

Ein getrimmter, nicht leerer String, auf max Zeichen gekürzt, sonst null. Nutze es für Namen, Item-Namen, Notizen, Suchtext.

Seite: Client, Server und NUI · Wartet: nein

Signatur
readText(value: unknown, max: number): string | null

Lua: kein Zwilling; prüfe type(value) == 'string', dann trimme und kürze ihn (value:sub(1, max)).

Parameter

Prop

Type

Rückgabewert

Der getrimmte Text (höchstens max Zeichen), oder null, wenn es kein String ist oder er nach dem Trimmen leer ist.

Beispiel

import { readText } from "@aicore-fivem/lib/shared";

readText("  Hello  ", 64);  // "Hello"
readText("   ", 64);        // null
readText(42, 64);           // null

readVec3

Ein Punkt aus Client- oder Export-Eingaben, jede Koordinate endlich, sonst null. Akzeptiert ein Objekt { x, y, z } und einen Lua-Vektor, der in TypeScript als Array [x, y, z] ankommt.

Seite: Client, Server und NUI · Wartet: nein

Signatur
readVec3(value: unknown): { x: number; y: number; z: number } | null

Lua: kein Zwilling; Lua-Code liest value.x, value.y, value.z (funktioniert für Vektoren und Tabellen).

Parameter

Prop

Type

Rückgabewert

Ein neues Vec3-Objekt, oder null.

Beispiel

resource/server/index.ts
import { registerExport } from "@aicore-fivem/lib/server";
import { readVec3, type Vec3 } from "@aicore-fivem/lib/shared";

const markers: Vec3[] = [];

// Funktioniert für exports["my-markers"].AddMarker(vector3(1, 2, 3)) aus Lua und AddMarker({ x: 1, y: 2, z: 3 }) aus TypeScript.
registerExport("AddMarker", (raw: unknown) => {
  const point = readVec3(raw);
  if (!point) return false;
  markers.push(point);
  return true;
});

readVec4

Ein Punkt mit Heading, sonst null. Akzeptiert { x, y, z, heading }, { x, y, z, w } und einen Lua-vector4 ([x, y, z, w]). Ein fehlendes Heading wird als 0 gelesen.

Seite: Client, Server und NUI · Wartet: nein

Signatur
readVec4(value: unknown): { x: number; y: number; z: number; heading: number } | null

Lua: kein Zwilling.

Parameter

Prop

Type

Rückgabewert

Ein neues Vec4-Objekt (heading 0, wenn keins angegeben wurde), oder null, wenn eine Koordinate oder das angegebene Heading keine endliche Zahl ist.

Beispiel

import { readVec4 } from "@aicore-fivem/lib/shared";

readVec4({ x: 1, y: 2, z: 3, w: 90 });  // { x: 1, y: 2, z: 3, heading: 90 }
readVec4([1, 2, 3]);                    // { x: 1, y: 2, z: 3, heading: 0 }
readVec4({ x: 1, y: 2 });               // null

oneArg

Macht aus einem Leser einen args-Parser für einen Callback oder ein Event, das genau einen Wert nimmt: { args: oneArg(readId) }.

Seite: Client, Server und NUI · Wartet: nein

Signatur
oneArg<T>(read: (value: unknown) => T | null): (args: unknown[]) => [T] | null

Lua: kein Zwilling.

Parameter

Prop

Type

Rückgabewert

Ein Parser, der [value] zurückgibt, oder null (lehnt den Aufruf ab), wenn read null zurückgegeben hat.

Beispiel

resource/server/index.ts
import { onClientCallback } from "@aicore-fivem/lib/server";
import { oneArg, readText } from "@aicore-fivem/lib/shared";

const notes = new Map<number, string>();

onClientCallback("my-notes:save", { args: oneArg((v) => readText(v, 500)) }, (source, text) => {
  notes.set(source, text);
  return { ok: true };
});

asArgs

Verpackt einen bereits geparsten Wert als args-Ergebnis: [value], oder null, wenn der Wert null ist. Nutze es, wenn deine eigene Prüffunktion den Wert oder null zurückgibt.

Seite: Client, Server und NUI · Wartet: nein

Signatur
asArgs<T>(value: T | null): [T] | null

Lua: kein Zwilling.

Parameter

Prop

Type

Rückgabewert

[value], oder null.

Beispiel

resource/server/index.ts
import { onClientCallback } from "@aicore-fivem/lib/server";
import { asArgs, toVehicleSetup, type VehicleSetup } from "@aicore-fivem/lib/shared";

const previews = new Map<number, VehicleSetup>();

onClientCallback("my-shop:preview", { args: ([raw]) => asArgs(toVehicleSetup(raw)) }, (source, setup) => {
  previews.set(source, setup);
  return { ok: true };
});

isRecord

Prüft, dass ein Wert ein einfaches Objekt ist (nicht null, kein Array).

Seite: Client, Server und NUI · Wartet: nein

Signatur
isRecord(value: unknown): value is Record<string, unknown>

Lua: kein Zwilling; prüfe type(value) == 'table'.

Parameter

Prop

Type

Rückgabewert

true für ein Objekt wie { a: 1 }. false für null, Arrays, Zahlen, Strings.

Beispiel

import { isRecord, readText } from "@aicore-fivem/lib/shared";

function readNote(raw: unknown): { title: string } | null {
  if (!isRecord(raw)) return null;
  const title = readText(raw.title, 80);
  return title === null ? null : { title };
}

Auf dieser Seite