Acciones y entrada del cliente
fail, isActionOk, replyError y los lectores estrictos readInt, readFinite, readId, readText, readVec3, readVec4, oneArg, asArgs, isRecord.
Todo lo que envía un cliente puede falsificarlo un tramposo: una cantidad negativa, una fracción donde esperas un número entero, un string de 10 MB, un objeto en lugar de un número. Los lectores estrictos de esta página convierten un valor en bruto en un valor comprobado, o en null para rechazarlo. Nunca reemplazan un valor incorrecto por uno por defecto (eso es lo que hacen los lectores de datos del panel, para los archivos que edita el dueño del servidor).
Cada acción del servidor responde un ActionResult: { ok: true } o un rechazo con una clave de idioma.
import { fail, isActionOk, replyError, readInt, readFinite, readId, readText, readVec3, readVec4, oneArg, asArgs, isRecord } from "@aicore-fivem/lib/shared";Dónde van los lectores: en la opción args de onClientCallback y onClientEvent (consulta Entrada del cliente). El parser recibe los argumentos en bruto como un array y devuelve los comprobados como un array, o null para rechazar la llamada antes de que se ejecute tu handler.
Resultados de acciones
fail
Construye un rechazo: { ok: false, error }. Devuélvelo desde un handler de acción; callAction del cliente muestra el texto traducido de error como notificación de error.
Lado: Cliente, servidor y NUI · Espera: no
fail(error: string): { ok: false; error: string }return aiLib.fail('NOT_ENOUGH_MONEY') -- { ok = false, error = 'NOT_ENOUGH_MONEY' }Parámetros
Prop
Type
Devuelve
{ ok: false, error: string }, que encaja en cualquier ActionResult.
Ejemplo
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 };
},
);En el cliente, callAction("my-shop:buyWater", [2], { fallback: "BUY_FAILED" }) (en Lua aiLib.callAction) muestra el rechazo por ti. Consulta Hablar con el servidor.
isActionOk
Comprueba si una respuesta es un ActionResult correcto (ok === true). Úsalo cuando lees una respuesta a mano en lugar de con callAction.
Lado: Cliente, servidor y NUI · Espera: no
isActionOk(reply: unknown): reply is { ok: true } & Record<string, unknown>Lua: sin equivalente; comprueba type(reply) == 'table' and reply.ok == true.
Parámetros
Prop
Type
Devuelve
true cuando reply es un objeto con ok: true. Los campos extra no se comprueban: procesa los que leas.
Ejemplo
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); // un campo extra: compruébalo como cualquier otra entrada
}replyError
La clave de idioma de una respuesta rechazada: su error, o fallback cuando la respuesta falta o está mal formada. null cuando la respuesta es ok.
Lado: Cliente, servidor y NUI · Espera: no
replyError(reply: unknown, fallback: string): string | nullLua: sin equivalente.
Parámetros
Prop
Type
Devuelve
null para una respuesta ok. En otro caso, el error de la respuesta cuando es un string no vacío, o si no fallback.
Ejemplo
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;
}Lectores estrictos
readFinite
Un número finito, o si no null. NaN, Infinity, el texto y todo lo demás se rechazan.
Lado: Cliente, servidor y NUI · Espera: no
readFinite(value: unknown): number | nullLua: sin equivalente; comprueba type(value) == 'number' and value == value and value ~= math.huge and value ~= -math.huge.
Parámetros
Prop
Type
Devuelve
El número, o null.
Ejemplo
import { readFinite } from "@aicore-fivem/lib/shared";
readFinite(12.5); // 12.5
readFinite(NaN); // null
readFinite("12"); // nullreadInt
Un número entero entre min y max (ambos incluidos), o si no null. Las fracciones, NaN, Infinity, el texto y los valores fuera de rango se rechazan. Úsalo para recuentos, cantidades, slots e índices.
Lado: Cliente, servidor y NUI · Espera: no
readInt(value: unknown, min: number, max: number): number | nullLua: sin equivalente; comprueba math.type(value) == 'integer' and value >= min and value <= max.
Parámetros
Prop
Type
Devuelve
El número, o null.
Ejemplo
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); // solo los objetos que vende esta tienda
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 número entero positivo de 32 bits (de 1 a 2.147.483.647), o si no null. Úsalo para los ids de registros, los tokens y los network ids que envía un cliente.
Lado: Cliente, servidor y NUI · Espera: no
readId(value: unknown): number | nullLua: sin equivalente; comprueba math.type(value) == 'integer' and value > 0 and value <= 2147483647.
Parámetros
Prop
Type
Devuelve
El id, o null.
Ejemplo
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 válido no es un objetivo válido. Comprueba siempre que el registro o la entidad existe, que el jugador puede usarlo y que está cerca de él.
readText
Un string recortado y no vacío, cortado a max caracteres, o si no null. Úsalo para nombres, nombres de objetos, notas y texto de búsqueda.
Lado: Cliente, servidor y NUI · Espera: no
readText(value: unknown, max: number): string | nullLua: sin equivalente; comprueba type(value) == 'string' y luego recórtalo y córtalo (value:sub(1, max)).
Parámetros
Prop
Type
Devuelve
El texto recortado (como máximo max caracteres), o null cuando no es un string o queda vacío tras recortarlo.
Ejemplo
import { readText } from "@aicore-fivem/lib/shared";
readText(" Hello ", 64); // "Hello"
readText(" ", 64); // null
readText(42, 64); // nullreadVec3
Un punto de la entrada de un cliente o de un export, con cada coordenada finita, o si no null. Acepta un objeto { x, y, z } y un vector de Lua, que llega a TypeScript como un array [x, y, z].
Lado: Cliente, servidor y NUI · Espera: no
readVec3(value: unknown): { x: number; y: number; z: number } | nullLua: sin equivalente; el código Lua lee value.x, value.y, value.z (funciona con vectores y tablas).
Parámetros
Prop
Type
Devuelve
Un objeto Vec3 nuevo, o null.
Ejemplo
import { registerExport } from "@aicore-fivem/lib/server";
import { readVec3, type Vec3 } from "@aicore-fivem/lib/shared";
const markers: Vec3[] = [];
// Funciona con exports["my-markers"].AddMarker(vector3(1, 2, 3)) desde Lua y AddMarker({ x: 1, y: 2, z: 3 }) desde TypeScript.
registerExport("AddMarker", (raw: unknown) => {
const point = readVec3(raw);
if (!point) return false;
markers.push(point);
return true;
});readVec4
Un punto con heading, o si no null. Acepta { x, y, z, heading }, { x, y, z, w } y un vector4 de Lua ([x, y, z, w]). Un heading que falta se lee como 0.
Lado: Cliente, servidor y NUI · Espera: no
readVec4(value: unknown): { x: number; y: number; z: number; heading: number } | nullLua: sin equivalente.
Parámetros
Prop
Type
Devuelve
Un objeto Vec4 nuevo (heading 0 cuando no se dio ninguno), o null cuando una coordenada o el heading dado no es un número finito.
Ejemplo
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
Convierte un lector en un parser args para un callback o evento que recibe exactamente un valor: { args: oneArg(readId) }.
Lado: Cliente, servidor y NUI · Espera: no
oneArg<T>(read: (value: unknown) => T | null): (args: unknown[]) => [T] | nullLua: sin equivalente.
Parámetros
Prop
Type
Devuelve
Un parser que devuelve [value], o null (rechaza la llamada) cuando read devolvió null.
Ejemplo
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
Envuelve un valor ya procesado como resultado de args: [value], o null cuando el valor es null. Úsalo cuando tu propia función de comprobación devuelve el valor o null.
Lado: Cliente, servidor y NUI · Espera: no
asArgs<T>(value: T | null): [T] | nullLua: sin equivalente.
Parámetros
Prop
Type
Devuelve
[value], o null.
Ejemplo
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
Comprueba que un valor es un objeto simple (ni null ni un array).
Lado: Cliente, servidor y NUI · Espera: no
isRecord(value: unknown): value is Record<string, unknown>Lua: sin equivalente; comprueba type(value) == 'table'.
Parámetros
Prop
Type
Devuelve
true para un objeto como { a: 1 }. false para null, arrays, números y strings.
Ejemplo
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 y los parsers stateNumber, stateBoolean, stateString: leer valores replicados desde la memoria.
Texto y números
formatText, round, groupDigits, formatWeight, stripGameText, randomInt, pickRandom y rollChance, además de dónde se documenta ServerClock.