AI Core
Referencia de la APIAI Core: exports de servidor

Objetos

Añade, quita, cuenta y comprueba objetos en cualquier inventario, registra alijos, tiendas de scripts y objetos usables, lee definiciones de objetos y el peso que se lleva.

Cada llamada de objetos pasa por ai-core, nunca por los exports propios de un script de inventario. ai-core reenvía cada llamada al inventario activo: el que elige el ajuste Inventory script (script de inventario) del panel, o el primero que esté en marcha cuando está en automático (ai-inventory, ox_inventory, qb-inventory, tgiann-inventory y los demás de la lista de compatibilidad). Cuando el dueño del servidor cambia de inventario, tu script sigue funcionando sin cambios.

Lo que debes saber:

  • Un inventario se nombra con un InventoryRef: el id de servidor de un jugador (un número) para los bolsillos de ese jugador, o un id de texto para cualquier otra cosa (un nombre de alijo, la matrícula de un maletero). Consulta InventoryRef.
  • Los nombres de objetos son los nombres de objeto del inventario (water, bandage, WEAPON_PISTOL).
  • Los metadatos son una tabla de valores extra en una pila (un número de serie, la durabilidad). Consulta ItemMetadata.
  • Mientras no hay ningún inventario en marcha, cada llamada responde su valor de "nada": false, 0, una lista vacía o null.
  • Los alijos, tiendas y objetos usables que registras los guarda ai-core y se los entrega a cada inventario que se active después, también tras reiniciar un inventario. Regístralos una vez cuando se inicie tu script.

AddItem

Da objetos a un inventario.

Lado: Servidor · Espera: no · Lib: inventory.addItem

Firma
AddItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): boolean
Lua
local ok = exports['ai-core']:AddItem(source, 'water', 2)

Parámetros

Prop

Type

Devuelve

boolean: true cuando el inventario añadió los objetos. false cuando no caben, el objeto no existe en el inventario, un argumento es erróneo (count menor que 1, nombre de objeto vacío) o no hay ningún inventario en marcha.

Ejemplo

import { onClientCallback, resourceExport, near } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";

const core = resourceExport("ai-core");
const TAP = { x: 1206.4, y: -3110.2, z: 5.6 };

onClientCallback("myscript:fillBottle", { guards: [near(TAP, 2)], lock: true }, (source) => {
  if (!core.RemoveItem(source, "empty_bottle")) return fail("NO_BOTTLE");
  if (!core.AddItem(source, "water")) {
    core.AddItem(source, "empty_bottle");
    return fail("NO_SPACE");
  }
  return { ok: true };
});

RemoveItem

Quita objetos de un inventario.

Lado: Servidor · Espera: no · Lib: inventory.removeItem

Firma
RemoveItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): boolean
Lua
local ok = exports['ai-core']:RemoveItem(source, 'lockpick', 1)

Parámetros

Prop

Type

Devuelve

boolean: true cuando se quitaron los objetos. false cuando el inventario tiene menos (entonces no se quita ninguno), un argumento es erróneo o no hay ningún inventario en marcha.

Ejemplo

import { onClientCallback, minigameFor, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";

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

onClientCallback("myscript:pickLock", { lock: true }, async (source) => {
  if (!core.HasItem(source, "lockpick")) return fail("NO_LOCKPICK");
  const result = await minigameFor(source, { game: "lockpick", minMs: 1500 });
  if (result === "broken") core.RemoveItem(source, "lockpick");
  return result === "won" ? { ok: true } : fail("LOCKPICK_FAILED");
});

GetItemCount

Cuántas unidades de un objeto tiene un inventario.

Lado: Servidor · Espera: no · Lib: inventory.getItemCount

Firma
GetItemCount(inv: InventoryRef, item: string, metadata?: ItemMetadata): number
Lua
local count = exports['ai-core']:GetItemCount(source, 'fish')

Parámetros

Prop

Type

Devuelve

number: el total de todas las pilas. 0 cuando no hay ninguno, un argumento es erróneo o no hay ningún inventario en marcha.

Ejemplo

import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";

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

// El comprador de pescado muestra cuánto recibiría el jugador.
onClientCallback("myscript:fishQuote", (source) => ({
  ok: true,
  price: core.GetItemCount(source, "fish") * 25,
}));

HasItem

Si un inventario tiene al menos cierta cantidad de un objeto.

Lado: Servidor · Espera: no · Lib: inventory.hasItem

Firma
HasItem(inv: InventoryRef, item: string, count?: number): boolean
Lua
local has = exports['ai-core']:HasItem(source, 'repairkit')

Parámetros

Prop

Type

Devuelve

boolean: true cuando el inventario tiene count o más. false cuando tiene menos, count es menor que 1 o no hay ningún inventario en marcha.

Ejemplo

import { onClientCallback, progressFor, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
import { Locale } from "common";

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

onClientCallback("myscript:repair", { lock: true }, async (source) => {
  if (!core.HasItem(source, "repairkit")) return fail("NO_KIT");
  if (!(await progressFor(source, { label: Locale("REPAIRING"), duration: 8000 }))) return fail("CANCELLED");
  if (!core.RemoveItem(source, "repairkit")) return fail("NO_KIT");
  return { ok: true };
});

Vuelve a comprobarlo con la respuesta de RemoveItem después de cualquier cosa que espere (una barra de progreso, un minijuego): el jugador puede haber tirado el objeto mientras tanto.

CanCarryItem

Si unos objetos cabrían en un inventario (peso y ranuras), sin añadirlos.

Lado: Servidor · Espera: no · Lib: inventory.canCarryItem

Firma
CanCarryItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata): boolean
Lua
local fits = exports['ai-core']:CanCarryItem(source, 'water', 5)

Parámetros

Prop

Type

Devuelve

boolean: true cuando caben. false cuando no caben, un argumento es erróneo o no hay ningún inventario en marcha.

Ejemplo

import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";

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

onClientCallback("myscript:buyWater", { lock: true }, (source) => {
  if (!core.CanCarryItem(source, "water", 5)) return fail("NO_SPACE");
  if (!core.RemoveMoney(source, "cash", 50, "shop_water")) return fail("NOT_ENOUGH_MONEY");
  core.AddItem(source, "water", 5);
  return { ok: true };
});

GetItems

Cada pila de un inventario, con etiquetas.

Lado: Servidor · Espera: no · Lib: inventory.getItems

Firma
GetItems(inv: InventoryRef): InventoryStack[]
Lua
local stacks = exports['ai-core']:GetItems(source) -- lista de tablas

Parámetros

Prop

Type

Devuelve

InventoryStack[]: una entrada por pila con name, label, count, slot y metadata. Consulta InventoryStack. Una lista vacía para un inventario vacío o desconocido, un argumento erróneo o si no hay ningún inventario en marcha.

Ejemplo

import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";

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

// Una casa de empeños lista cada objeto que lleva el jugador y que ella compra.
const BUYS: Record<string, number> = { gold_ring: 120, rolex: 400 };

onClientCallback("myscript:pawnList", (source) => ({
  ok: true,
  rows: core.GetItems(source)
    .filter((stack) => BUYS[stack.name] !== undefined)
    .map((stack) => ({ slot: stack.slot, label: stack.label, count: stack.count, price: BUYS[stack.name] })),
}));

ClearInventory

Vacía un inventario por completo.

Lado: Servidor · Espera: no · Lib: inventory.clearInventory

Firma
ClearInventory(inv: InventoryRef): void
Lua
exports['ai-core']:ClearInventory(source)

Parámetros

Prop

Type

Devuelve

Nada. Un argumento erróneo o la falta de un inventario en marcha no hace nada.

Ejemplo

import { addCommand, resourceExport } from "@aicore-fivem/lib/server";

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

addCommand("clearinv", { help: "Empties a player inventory", params: [{ name: "id", type: "playerId" }], restricted: true }, (_source, args) => {
  core.ClearInventory(args.id);
});

Esto no se puede deshacer. Ponlo detrás de un comando de admin o de una regla de juego clara (un ingreso en prisión que antes guarda los objetos).

RegisterStash

Crea un alijo: una caja de almacenamiento que los jugadores abren por su nombre. ai-core lo guarda y lo vuelve a registrar en cada inventario que se active.

Lado: Servidor · Espera: no · Lib: inventory.registerStash

Firma
RegisterStash(name: string, label: string, slots: number, maxWeight: number, jobs?: string[]): void
Lua
exports['ai-core']:RegisterStash('police_evidence', 'Evidence', 100, 500000, { 'police' })

Parámetros

Prop

Type

Los valores por defecto se aplican cuando un valor falta o es erróneo.

Devuelve

Nada. Sin un name de texto la llamada no hace nada. Registrar de nuevo el mismo nombre reemplaza el alijo.

Ejemplo

import { onClientCallback, resourceExport, near } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
import { Locale } from "common";

const core = resourceExport("ai-core");
const LOCKER = { x: 474.9, y: -994.7, z: 26.3 };

// Una vez al iniciar; ai-core se lo entrega a los inventarios que se inicien más tarde.
core.RegisterStash("police_evidence", Locale("STASH_EVIDENCE"), 100, 500_000, ["police"]);

onClientCallback("myscript:openEvidence", { guards: [near(LOCKER, 2)] }, (source) => {
  if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
  return core.OpenInventory(source, "police_evidence") ? { ok: true } : fail("STASH_FAILED");
});

OpenInventory

Abre un alijo, un maletero o el inventario de otro jugador en la pantalla de un jugador, junto al suyo propio.

Lado: Servidor · Espera: no · Lib: inventory.openInventory

Firma
OpenInventory(source: number, inv: InventoryRef): boolean
Lua
local opened = exports['ai-core']:OpenInventory(source, 'police_evidence')

Parámetros

Prop

Type

Devuelve

boolean: true cuando el inventario abrió la pantalla. false cuando no pudo (alijo desconocido, el jugador no tiene inventario), un argumento es erróneo o no hay ningún inventario en marcha.

Ejemplo

import { onClientCallback, isNear, coordsOf, resourceExport } from "@aicore-fivem/lib/server";
import { fail, oneArg, readId } from "@aicore-fivem/lib/shared";

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

// La policía cachea a un jugador esposado que tiene al lado.
onClientCallback("myscript:search", { args: oneArg(readId) }, (source, target) => {
  if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
  if (target === source || !isNear(target, coordsOf(source), 2)) return fail("TOO_FAR");
  return core.OpenInventory(source, target) ? { ok: true } : fail("SEARCH_FAILED");
});

Aquí el inventario no comprueba ni la distancia ni los permisos. Comprueba tú el trabajo, la distancia y el estado del objetivo antes de llamarlo.

RegisterShop

Crea una tienda de script: una lista de objetos con precios que tu script abre para un jugador (una armería, una máquina expendedora). El inventario dibuja la tienda y cobra a su manera (efectivo y luego banco). ai-core la guarda y se la entrega a cada inventario que se active.

Lado: Servidor · Espera: no · Lib: inventory.registerShop

Firma
RegisterShop(name: string, label: string, items: ShopProduct[]): void
Lua
exports['ai-core']:RegisterShop('police_armoury', 'Armoury', { { name = 'bandage', price = 0 } })

Parámetros

Prop

Type

Consulta ShopProduct.

Devuelve

Nada. Sin un name de texto o sin ningún producto válido la llamada no hace nada. Registrar de nuevo el mismo nombre reemplaza la tienda.

Ejemplo

import { onClientCallback, resourceExport, near } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
import { Locale } from "common";

const core = resourceExport("ai-core");
const ARMOURY = { x: 482.6, y: -995.2, z: 30.7 };

core.RegisterShop("police_armoury", Locale("SHOP_ARMOURY"), [
  { name: "WEAPON_STUNGUN", price: 0 },
  { name: "bandage", price: 10 },
]);

onClientCallback("myscript:armoury", { guards: [near(ARMOURY, 2)] }, (source) => {
  if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
  return core.OpenShop(source, "police_armoury") ? { ok: true } : fail("SHOP_FAILED");
});

OpenShop

Abre en la pantalla de un jugador una tienda registrada con RegisterShop.

Lado: Servidor · Espera: no · Lib: inventory.openShop

Firma
OpenShop(source: number, name: string): boolean
Lua
local opened = exports['ai-core']:OpenShop(source, 'police_armoury')

Parámetros

Prop

Type

Devuelve

boolean: true cuando se abrió la tienda. false cuando ninguna tienda tiene ese nombre, el inventario activo no tiene tiendas de scripts, no pudo abrirla o no hay ningún inventario en marcha.

Ejemplo

Consulta el ejemplo de RegisterShop de arriba: regístrala una vez al iniciar y ábrela después de tus propias comprobaciones de trabajo y distancia.

Igual que OpenInventory, esto no comprueba la distancia ni el acceso. Compruébalos antes.

RegisterUsableItem

Hace usable un objeto: cuando un jugador lo usa en el inventario, se ejecuta tu función. ai-core guarda la función, así que funciona con inventarios que se inicien más tarde y sobrevive a un reinicio del inventario.

Lado: Servidor · Espera: no · Lib: inventory.registerUsableItem

Firma
RegisterUsableItem(name: string, handler: UsableItemHandler): void
// UsableItemHandler = (source: number, item: UsedItem) => unknown
Lua
exports['ai-core']:RegisterUsableItem('bandage', function(source, item) end)

Parámetros

Prop

Type

Consulta UsableItemHandler y UsedItem.

Devuelve

Nada. Sin un name de texto o una función la llamada no hace nada. Una segunda llamada para el mismo objeto reemplaza el handler.

Lo que le pasa al objeto tras usarlo depende del inventario: los inventarios que retiran ellos mismos el objeto usado (ai-inventory retira la cantidad consume del objeto) lo conservan cuando tu handler devuelve false; los demás inventarios siguen sus propios ajustes de objeto, así que ahí quita tú el objeto cuando haga falta.

Ejemplo

import { progressFor, resourceExport } from "@aicore-fivem/lib/server";
import { Locale } from "common";

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

core.RegisterUsableItem("bandage", (source) => {
  // El handler debe responder al momento; la parte temporizada corre por su cuenta.
  void (async () => {
    if (!(await progressFor(source, { label: Locale("BANDAGING"), duration: 4000 }))) return;
    if (!core.RemoveItem(source, "bandage")) return;
    emitNet("myscript:client:heal", source, 25); // tu script de cliente añade la salud
  })();
  return false; // se conserva: se quita arriba cuando termina la barra
});

Un uso también dispara el evento de servidor ai-core:itemUsed (src, name, status), que siguen efectos de objetos como el hambre y la sed. Consulta Eventos y estado.

GetItemDefinition

Un objeto tal como lo define el inventario activo: etiqueta, peso, si se apila, imagen.

Lado: Servidor · Espera: no · Lib: inventory.getItemDefinition

Firma
GetItemDefinition(name: string): ItemDefinition | null
Lua
local def = exports['ai-core']:GetItemDefinition('water') -- table o nil

Parámetros

Prop

Type

Devuelve

ItemDefinition | null: el objeto con name, label, weight, unique, close, description e image cuando el inventario tiene una. Consulta ItemDefinition. null para un objeto desconocido, un nombre vacío o si no hay ningún inventario en marcha.

Ejemplo

import { notify, resourceExport } from "@aicore-fivem/lib/server";
import { Locale } from "common";

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

/** "You received 2x Water" with the inventory's own label. */
export function giveWithNotice(source: number, item: string, count: number): void {
  if (!core.AddItem(source, item, count)) return;
  const label = core.GetItemDefinition(item)?.label ?? item;
  notify(source, Locale("NOTIFY_RECEIVED", count, label), "success");
}

GetItemDefinitions

Cada objeto que define el inventario activo, con el nombre como clave. Úsalo poco (construir una lista una vez); para un solo objeto usa GetItemDefinition.

Lado: Servidor · Espera: no · Lib: ninguna

Firma
GetItemDefinitions(): Record<string, ItemDefinition>
Lua
local items = exports['ai-core']:GetItemDefinitions() -- tabla con el nombre del objeto como clave

Parámetros

Ninguno.

Devuelve

Record<string, ItemDefinition>: cada objeto. Una tabla vacía mientras no hay ningún inventario en marcha.

Ejemplo

import { resourceExport } from "@aicore-fivem/lib/server";

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

/** Warns at start about items in your config that the inventory does not know. */
export function checkItems(names: string[]): void {
  const known = core.GetItemDefinitions();
  for (const name of names) if (!known[name]) console.log(`unknown item: ${name}`);
}

Haz una comprobación así después de que se inicie el inventario: justo tras arrancar el servidor puede que el inventario aún no esté en marcha y la tabla esté vacía.

GetInventoryWeight

Lo que lleva un jugador y lo que puede llevar, por peso.

Lado: Servidor · Espera: no · Lib: ninguna

Firma
GetInventoryWeight(source: number): { weight: number; maxWeight: number } | null
Lua
local w = exports['ai-core']:GetInventoryWeight(source) -- { weight, maxWeight } o nil

Parámetros

Prop

Type

Devuelve

{ weight, maxWeight } | null: el peso que lleva y el límite, en gramos. null cuando el inventario activo no los indica, el jugador no tiene un inventario cargado o no hay ningún inventario en marcha.

Ejemplo

import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";

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

onClientCallback("myscript:weight", (source) => {
  const w = core.GetInventoryWeight(source);
  return { ok: true, free: w ? w.maxWeight - w.weight : null };
});

UseItem

Ejecuta el handler registrado para un objeto, como si el jugador lo usara. Lo llama el puente de ESX / QB de ai-core (desde ESX.UseItem y el CanUseItem de QB); un script normal no tiene motivo para hacerlo.

Lado: Servidor · Espera: no · Lib: ninguna (solo el puente)

Firma
UseItem(source: number, name: string, item?: unknown): unknown
Lua
local result = exports['ai-core']:UseItem(source, 'bandage', stack)

Parámetros

Prop

Type

Devuelve

unknown: lo que devolvió el handler. false cuando no hay ningún handler registrado, los argumentos son erróneos o el handler lanzó un error (queda en el log).

Ejemplo

Sin ejemplo: lo llaman los inventarios y el puente. Para reaccionar a un uso, registra el objeto con RegisterUsableItem.

IsUsableItem

Si hay un handler registrado para un objeto. Lo usa el puente de ai-core.

Lado: Servidor · Espera: no · Lib: ninguna (solo el puente)

Firma
IsUsableItem(name: string): boolean
Lua
local usable = exports['ai-core']:IsUsableItem('bandage')

Parámetros

Prop

Type

Devuelve

boolean: true cuando algún recurso registró el objeto con RegisterUsableItem. false en otro caso.

Ejemplo

import { resourceExport } from "@aicore-fivem/lib/server";

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

/** Item tooltips show "Use" only for usable items. */
export function canUse(item: string): boolean {
  return core.IsUsableItem(item);
}

En esta página