AI Core
Référence de l’APIAI Core : exports serveur

Objets

Ajouter, retirer, compter et vérifier des objets dans n’importe quel inventaire, enregistrer des coffres, des magasins de script et des objets utilisables, lire les définitions d’objets et le poids porté.

Chaque appel d’objet passe par ai-core, jamais par les exports propres à un script d’inventaire. ai-core transmet chaque appel à l’inventaire actif : celui que choisit le réglage Inventory script du panneau, ou le premier qui tourne quand il est en automatique (ai-inventory, ox_inventory, qb-inventory, tgiann-inventory et les autres de la liste de compatibilité). Quand le propriétaire du serveur change d’inventaire, votre script continue de fonctionner sans modification.

Ce qu’il faut savoir :

  • Un inventaire est désigné par un InventoryRef : l’id serveur d’un joueur (un nombre) pour les poches de ce joueur, ou un id texte pour tout le reste (un nom de coffre, une plaque de coffre de véhicule). Voir InventoryRef.
  • Les noms d’objets sont les noms d’objets de l’inventaire (water, bandage, WEAPON_PISTOL).
  • Les métadonnées sont une table de valeurs supplémentaires sur une pile (un numéro de série, une durabilité). Voir ItemMetadata.
  • Tant qu’aucun inventaire ne tourne, chaque appel répond sa valeur « rien » : false, 0, une liste vide ou null.
  • Les coffres, magasins et objets utilisables que vous enregistrez sont gardés par ai-core et transmis à chaque inventaire qui devient actif plus tard, y compris après un redémarrage de l’inventaire. Enregistrez-les une fois au démarrage de votre script.

AddItem

Donne des objets à un inventaire.

Côté : Serveur · Attend : non · Lib : inventory.addItem

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

Paramètres

Prop

Type

Retour

boolean : true quand l’inventaire a ajouté les objets. false quand ils ne tiennent pas, que l’objet n’existe pas dans l’inventaire, qu’un argument est incorrect (count inférieur à 1, nom d’objet vide) ou qu’aucun inventaire ne tourne.

Exemple

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

Retire des objets d’un inventaire.

Côté : Serveur · Attend : non · Lib : inventory.removeItem

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

Paramètres

Prop

Type

Retour

boolean : true quand les objets ont été retirés. false quand l’inventaire en contient moins (aucun n’est alors retiré), qu’un argument est incorrect ou qu’aucun inventaire ne tourne.

Exemple

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

Combien d’un objet contient un inventaire.

Côté : Serveur · Attend : non · Lib : inventory.getItemCount

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

Paramètres

Prop

Type

Retour

number : le total sur toutes les piles. 0 quand il n’y en a aucune, qu’un argument est incorrect ou qu’aucun inventaire ne tourne.

Exemple

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

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

// L’acheteur de poisson montre combien le joueur recevrait.
onClientCallback("myscript:fishQuote", (source) => ({
  ok: true,
  price: core.GetItemCount(source, "fish") * 25,
}));

HasItem

Indique si un inventaire contient au moins une quantité d’un objet.

Côté : Serveur · Attend : non · Lib : inventory.hasItem

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

Paramètres

Prop

Type

Retour

boolean : true quand l’inventaire en contient count ou plus. false quand il en contient moins, que count est inférieur à 1, ou qu’aucun inventaire ne tourne.

Exemple

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 };
});

Revérifiez avec la réponse de RemoveItem après tout ce qui attend (une barre de progression, un mini-jeu) : le joueur a pu jeter l’objet entre-temps.

CanCarryItem

Indique si des objets tiendraient dans un inventaire (poids et emplacements), sans les ajouter.

Côté : Serveur · Attend : non · Lib : inventory.canCarryItem

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

Paramètres

Prop

Type

Retour

boolean : true quand ils tiennent. false quand ils ne tiennent pas, qu’un argument est incorrect ou qu’aucun inventaire ne tourne.

Exemple

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

Chaque pile d’un inventaire, avec libellés.

Côté : Serveur · Attend : non · Lib : inventory.getItems

Signature
GetItems(inv: InventoryRef): InventoryStack[]
Lua
local stacks = exports['ai-core']:GetItems(source) -- liste de tables

Paramètres

Prop

Type

Retour

InventoryStack[] : une entrée par pile avec name, label, count, slot et metadata. Voir InventoryStack. Une liste vide pour un inventaire vide ou inconnu, un argument incorrect ou aucun inventaire en cours.

Exemple

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

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

// Un prêteur sur gages liste chaque objet que porte le joueur et qu’il rachète.
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

Vide complètement un inventaire.

Côté : Serveur · Attend : non · Lib : inventory.clearInventory

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

Paramètres

Prop

Type

Retour

Rien. Un argument incorrect ou l’absence d’inventaire en cours ne fait rien.

Exemple

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);
});

Ceci est irréversible. Gardez-le derrière une commande d’admin ou une règle de jeu claire (une entrée en prison qui stocke d’abord les objets).

RegisterStash

Crée un coffre : une boîte de stockage que les joueurs ouvrent par son nom. ai-core le garde et l’enregistre de nouveau auprès de chaque inventaire qui devient actif.

Côté : Serveur · Attend : non · Lib : inventory.registerStash

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

Paramètres

Prop

Type

Les valeurs par défaut s’appliquent quand une valeur manque ou est incorrecte.

Retour

Rien. Sans name texte, l’appel ne fait rien. Enregistrer de nouveau le même nom remplace le coffre.

Exemple

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 };

// Une fois au démarrage ; ai-core le transmet aux inventaires qui démarrent plus tard.
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

Ouvre un coffre, un coffre de véhicule ou l’inventaire d’un autre joueur sur l’écran d’un joueur, à côté du sien.

Côté : Serveur · Attend : non · Lib : inventory.openInventory

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

Paramètres

Prop

Type

Retour

boolean : true quand l’inventaire a ouvert l’écran. false quand il n’a pas pu (coffre inconnu, le joueur n’a pas d’inventaire), qu’un argument est incorrect ou qu’aucun inventaire ne tourne.

Exemple

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 police fouille un joueur menotté debout à côté d’elle.
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");
});

L’inventaire ne fait ici aucune vérification de distance ni de permission. Vérifiez vous-même le métier, la distance et l’état de la cible avant de l’appeler.

RegisterShop

Crée un magasin de script : une liste d’objets avec des prix que votre script ouvre pour un joueur (une armurerie, un distributeur automatique). L’inventaire dessine le magasin et prend le paiement à sa façon (liquide, puis banque). ai-core le garde et le transmet à chaque inventaire qui devient actif.

Côté : Serveur · Attend : non · Lib : inventory.registerShop

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

Paramètres

Prop

Type

Voir ShopProduct.

Retour

Rien. Sans name texte ou sans produit valide, l’appel ne fait rien. Enregistrer de nouveau le même nom remplace le magasin.

Exemple

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

Ouvre sur l’écran d’un joueur un magasin enregistré avec RegisterShop.

Côté : Serveur · Attend : non · Lib : inventory.openShop

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

Paramètres

Prop

Type

Retour

boolean : true quand le magasin s’est ouvert. false quand aucun magasin ne porte ce nom, que l’inventaire actif n’a pas de magasins de script, qu’il n’a pas pu l’ouvrir, ou qu’aucun inventaire ne tourne.

Exemple

Voir l’exemple de RegisterShop ci-dessus : enregistrez une fois au démarrage, puis ouvrez après vos propres vérifications de métier et de distance.

Comme OpenInventory, ceci ne fait aucune vérification de distance ni d’accès. Vérifiez-les d’abord.

RegisterUsableItem

Rend un objet utilisable : quand un joueur l’utilise dans l’inventaire, votre fonction s’exécute. ai-core garde la fonction, elle fonctionne donc avec les inventaires qui démarrent plus tard et survit à un redémarrage de l’inventaire.

Côté : Serveur · Attend : non · Lib : inventory.registerUsableItem

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

Paramètres

Prop

Type

Voir UsableItemHandler et UsedItem.

Retour

Rien. Sans name texte ou sans fonction, l’appel ne fait rien. Un second appel pour le même objet remplace le handler.

Ce qu’il advient de l’objet après utilisation dépend de l’inventaire : les inventaires qui retirent eux-mêmes un objet utilisé (ai-inventory retire la quantité consume de l’objet) le gardent quand votre handler renvoie false ; les autres inventaires suivent leurs propres réglages d’objets, retirez donc l’objet vous-même là où c’est nécessaire.

Exemple

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

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

core.RegisterUsableItem("bandage", (source) => {
  // Le handler doit répondre tout de suite ; la partie temporisée tourne d’elle-même.
  void (async () => {
    if (!(await progressFor(source, { label: Locale("BANDAGING"), duration: 4000 }))) return;
    if (!core.RemoveItem(source, "bandage")) return;
    emitNet("myscript:client:heal", source, 25); // votre script client ajoute la santé
  })();
  return false; // le garder : il est retiré plus haut une fois la barre terminée
});

Une utilisation déclenche aussi l’événement serveur ai-core:itemUsed (src, name, status), que suivent les effets d’objets comme la faim et la soif. Voir Événements et état.

GetItemDefinition

Un objet tel que le définit l’inventaire actif : libellé, poids, s’il s’empile, image.

Côté : Serveur · Attend : non · Lib : inventory.getItemDefinition

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

Paramètres

Prop

Type

Retour

ItemDefinition | null : l’objet avec name, label, weight, unique, close, description et image quand l’inventaire en a une. Voir ItemDefinition. null pour un objet inconnu, un nom vide ou aucun inventaire en cours.

Exemple

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

Chaque objet que définit l’inventaire actif, indexé par nom. Utilisez-le rarement (construire une liste une fois) ; pour un seul objet, utilisez GetItemDefinition.

Côté : Serveur · Attend : non · Lib : aucune

Signature
GetItemDefinitions(): Record<string, ItemDefinition>
Lua
local items = exports['ai-core']:GetItemDefinitions() -- table indexée par nom d’objet

Paramètres

Aucun.

Retour

Record<string, ItemDefinition> : chaque objet. Une table vide tant qu’aucun inventaire ne tourne.

Exemple

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}`);
}

Faites une telle vérification après le démarrage de l’inventaire : juste après un démarrage du serveur, l’inventaire peut ne pas encore tourner et la table est vide.

GetInventoryWeight

Ce que porte un joueur et ce qu’il peut porter, en poids.

Côté : Serveur · Attend : non · Lib : aucune

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

Paramètres

Prop

Type

Retour

{ weight, maxWeight } | null : le poids porté et la limite, en grammes. null quand l’inventaire actif ne les donne pas, que le joueur n’a pas d’inventaire chargé ou qu’aucun inventaire ne tourne.

Exemple

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

Exécute le handler enregistré pour un objet, comme si le joueur l’avait utilisé. Le pont ESX / QB d’ai-core l’appelle (depuis ESX.UseItem et CanUseItem de QB) ; un script normal n’a aucune raison de le faire.

Côté : Serveur · Attend : non · Lib : aucune (pont uniquement)

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

Paramètres

Prop

Type

Retour

unknown : ce que le handler a renvoyé. false quand aucun handler n’est enregistré, que les arguments sont incorrects ou que le handler a levé une erreur (elle est enregistrée dans le log).

Exemple

Pas d’exemple : les inventaires et le pont l’appellent. Pour réagir à une utilisation, enregistrez l’objet avec RegisterUsableItem.

IsUsableItem

Indique si un handler est enregistré pour un objet. Le pont d’ai-core l’utilise.

Côté : Serveur · Attend : non · Lib : aucune (pont uniquement)

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

Paramètres

Prop

Type

Retour

boolean : true quand une ressource a enregistré l’objet avec RegisterUsableItem. false sinon.

Exemple

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);
}

Sur cette page