Actions et entrées du client
fail, isActionOk, replyError et les lecteurs stricts readInt, readFinite, readId, readText, readVec3, readVec4, oneArg, asArgs, isRecord.
Tout ce qu’envoie un client peut être falsifié par un tricheur : un montant négatif, une fraction là où vous attendez un nombre entier, une chaîne de 10 Mo, un objet au lieu d’un nombre. Les lecteurs stricts de cette page transforment une valeur brute en valeur vérifiée, ou en null pour la refuser. Ils ne remplacent jamais une mauvaise valeur par une valeur par défaut (c’est le rôle des lecteurs de données du panneau, pour les fichiers que modifie le propriétaire du serveur).
Chaque action serveur répond par un ActionResult : { ok: true } ou un refus avec une clé de langue.
import { fail, isActionOk, replyError, readInt, readFinite, readId, readText, readVec3, readVec4, oneArg, asArgs, isRecord } from "@aicore-fivem/lib/shared";Où vont les lecteurs : dans l’option args de onClientCallback et de onClientEvent (voir Entrées client). Le parseur reçoit les arguments bruts sous forme de tableau et renvoie ceux qui sont vérifiés sous forme de tableau, ou null pour refuser l’appel avant que votre gestionnaire s’exécute.
Résultats d’action
fail
Construit un refus : { ok: false, error }. Renvoyez-le depuis un gestionnaire d’action ; callAction côté client affiche le texte traduit de error dans une notification d’erreur.
Côté : client, serveur et NUI · Attend : non
fail(error: string): { ok: false; error: string }return aiLib.fail('NOT_ENOUGH_MONEY') -- { ok = false, error = 'NOT_ENOUGH_MONEY' }Paramètres
Prop
Type
Retour
{ ok: false, error: string }, qui convient à n’importe quel ActionResult.
Exemple
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 };
},
);Sur le client, callAction("my-shop:buyWater", [2], { fallback: "BUY_FAILED" }) (Lua aiLib.callAction) affiche le refus pour vous. Voir Parler au serveur.
isActionOk
Vérifie si une réponse est un ActionResult réussi (ok === true). Utilisez-le quand vous lisez une réponse à la main plutôt qu’avec callAction.
Côté : client, serveur et NUI · Attend : non
isActionOk(reply: unknown): reply is { ok: true } & Record<string, unknown>Lua : pas d’équivalent ; vérifiez type(reply) == 'table' and reply.ok == true.
Paramètres
Prop
Type
Retour
true quand reply est un objet avec ok: true. Les champs en plus ne sont pas vérifiés : parsez ceux que vous lisez.
Exemple
import { triggerServerCallback } from "@aicore-fivem/lib/client";
import { isActionOk, readId } from "@aicore-fivem/lib/shared";
/** Demande au serveur de créer un garage ; renvoie son nouvel id, ou 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); // un champ en plus : vérifiez-le comme n’importe quelle entrée
}replyError
La clé de langue d’une réponse refusée : son error, ou fallback quand la réponse manque ou est mal formée. null quand la réponse est réussie.
Côté : client, serveur et NUI · Attend : non
replyError(reply: unknown, fallback: string): string | nullLua : pas d’équivalent.
Paramètres
Prop
Type
Retour
null pour une réponse réussie. Sinon l’error de la réponse quand c’est une chaîne non vide, à défaut fallback.
Exemple
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;
}Lecteurs stricts
readFinite
Un nombre fini, sinon null. NaN, Infinity, le texte et tout le reste sont refusés.
Côté : client, serveur et NUI · Attend : non
readFinite(value: unknown): number | nullLua : pas d’équivalent ; vérifiez type(value) == 'number' and value == value and value ~= math.huge and value ~= -math.huge.
Paramètres
Prop
Type
Retour
Le nombre, ou null.
Exemple
import { readFinite } from "@aicore-fivem/lib/shared";
readFinite(12.5); // 12.5
readFinite(NaN); // null
readFinite("12"); // nullreadInt
Un nombre entier entre min et max (tous deux inclus), sinon null. Les fractions, NaN, Infinity, le texte et les valeurs hors plage sont refusés. Utilisez-le pour des quantités, des montants, des emplacements, des index.
Côté : client, serveur et NUI · Attend : non
readInt(value: unknown, min: number, max: number): number | nullLua : pas d’équivalent ; vérifiez math.type(value) == 'integer' and value >= min and value <= max.
Paramètres
Prop
Type
Retour
Le nombre, ou null.
Exemple
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); // seulement les objets que vend ce magasin
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
Un nombre entier positif sur 32 bits (1 à 2 147 483 647), sinon null. Utilisez-le pour les id d’enregistrement, les jetons et les network id qu’envoie un client.
Côté : client, serveur et NUI · Attend : non
readId(value: unknown): number | nullLua : pas d’équivalent ; vérifiez math.type(value) == 'integer' and value > 0 and value <= 2147483647.
Paramètres
Prop
Type
Retour
L’id, ou null.
Exemple
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 };
});Un id valide n’est pas une cible valide. Vérifiez toujours que l’enregistrement ou l’entité existe, que le joueur a le droit de l’utiliser et qu’il en est proche.
readText
Une chaîne non vide, sans espaces autour, coupée à max caractères, sinon null. Utilisez-le pour des noms, des noms d’objet, des notes, un texte de recherche.
Côté : client, serveur et NUI · Attend : non
readText(value: unknown, max: number): string | nullLua : pas d’équivalent ; vérifiez type(value) == 'string', puis retirez les espaces autour et coupez (value:sub(1, max)).
Paramètres
Prop
Type
Retour
Le texte sans espaces autour (au plus max caractères), ou null quand ce n’est pas une chaîne ou qu’elle est vide une fois les espaces retirés.
Exemple
import { readText } from "@aicore-fivem/lib/shared";
readText(" Hello ", 64); // "Hello"
readText(" ", 64); // null
readText(42, 64); // nullreadVec3
Un point venant d’une entrée client ou d’un export, chaque coordonnée finie, sinon null. Accepte un objet { x, y, z } et un vecteur Lua, qui arrive en TypeScript sous forme de tableau [x, y, z].
Côté : client, serveur et NUI · Attend : non
readVec3(value: unknown): { x: number; y: number; z: number } | nullLua : pas d’équivalent ; le code Lua lit value.x, value.y, value.z (fonctionne pour les vecteurs et les tables).
Paramètres
Prop
Type
Retour
Un nouvel objet Vec3, ou null.
Exemple
import { registerExport } from "@aicore-fivem/lib/server";
import { readVec3, type Vec3 } from "@aicore-fivem/lib/shared";
const markers: Vec3[] = [];
// Fonctionne pour exports["my-markers"].AddMarker(vector3(1, 2, 3)) depuis Lua et AddMarker({ x: 1, y: 2, z: 3 }) depuis TypeScript.
registerExport("AddMarker", (raw: unknown) => {
const point = readVec3(raw);
if (!point) return false;
markers.push(point);
return true;
});readVec4
Un point avec un cap, sinon null. Accepte { x, y, z, heading }, { x, y, z, w } et un vector4 Lua ([x, y, z, w]). Un cap manquant est lu comme 0.
Côté : client, serveur et NUI · Attend : non
readVec4(value: unknown): { x: number; y: number; z: number; heading: number } | nullLua : pas d’équivalent.
Paramètres
Prop
Type
Retour
Un nouvel objet Vec4 (heading à 0 quand aucun n’a été donné), ou null quand une coordonnée ou le cap donné n’est pas un nombre fini.
Exemple
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 }); // nulloneArg
Transforme un lecteur en parseur args pour un callback ou un événement qui prend exactement une valeur : { args: oneArg(readId) }.
Côté : client, serveur et NUI · Attend : non
oneArg<T>(read: (value: unknown) => T | null): (args: unknown[]) => [T] | nullLua : pas d’équivalent.
Paramètres
Prop
Type
Retour
Un parseur qui renvoie [value], ou null (refuse l’appel) quand read a renvoyé null.
Exemple
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
Emballe une valeur déjà parsée en résultat args : [value], ou null quand la valeur est null. Utilisez-le quand votre propre fonction de vérification renvoie la valeur ou null.
Côté : client, serveur et NUI · Attend : non
asArgs<T>(value: T | null): [T] | nullLua : pas d’équivalent.
Paramètres
Prop
Type
Retour
[value], ou null.
Exemple
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
Vérifie qu’une valeur est un objet simple (ni null, ni un tableau).
Côté : client, serveur et NUI · Attend : non
isRecord(value: unknown): value is Record<string, unknown>Lua : pas d’équivalent ; vérifiez type(value) == 'table'.
Paramètres
Prop
Type
Retour
true pour un objet comme { a: 1 }. false pour null, les tableaux, les nombres, les chaînes.
Exemple
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 };
}State bags
EntityState, PlayerState, GlobalKey, GlobalGroup et les parseurs stateNumber, stateBoolean, stateString : lire les valeurs répliquées depuis la mémoire.
Texte et nombres
formatText, round, groupDigits, formatWeight, stripGameText, randomInt, pickRandom et rollChance, et l’endroit où ServerClock est documenté.