Événements serveur
Chaque événement local côté serveur que déclenche ai-core - personnages, argent, métiers, service, gangs, métadonnées, définitions, objets, morts - avec arguments et écouteurs en TypeScript et en Lua.
ai-core déclenche ces événements sur le serveur avec TriggerEvent (locaux : les autres ressources serveur les entendent, les clients jamais). Le miroir online de la lib et les ponts ESX / QB / vRP reposent dessus ; c’est donc le moyen le moins coûteux de suivre les joueurs : aucun appel d’export, aucune interrogation en boucle.
Le handler de chaque événement s’exécute de façon synchrone pendant qu’ai-core est au milieu du changement : gardez les handlers courts et n’attendez jamais à l’intérieur. Si vous devez attendre (une écriture en base de données), lancez-la sans bloquer.
ai-core:playerLoaded
Le personnage d’un joueur a été chargé et ses données envoyées à son client. Se déclenche une fois par chargement de personnage, aussi après un changement de personnage. Avec le choix d’apparition activé, il se déclenche avant que le joueur choisisse où apparaître ; ai-core:playerSpawned suit le choix.
Côté : Serveur · Constante : CORE.playerLoadedEvent
Arguments
Prop
Type
Écouteur
import { CORE, type CharacterInfo } from "@aicore-fivem/shared";
on(CORE.playerLoadedEvent, (src: number, character: CharacterInfo) => {
console.log(`#${character.id} ${character.firstname} ${character.lastname} loaded (src ${src})`);
});Les personnages déjà chargés avant le démarrage de votre ressource ne le déclenchent jamais pour vous. Utilisez onCharacter({ loaded }) de la lib (aiLib.onCharacter en Lua), qui les rejoue.
ai-core:playerSpawned
Le personnage chargé a été placé dans le monde. Se déclenche juste après ai-core:playerLoaded, ou après que le joueur a choisi un point d’apparition quand le serveur le laisse choisir. Utilisez-le pour ce qui a besoin du ped dans le monde (un message de bienvenue, une téléportation).
Côté : Serveur · Constante : CORE.playerSpawnedEvent
Arguments
Prop
Type
Écouteur
import { notify } from "@aicore-fivem/lib/server";
import { CORE } from "@aicore-fivem/shared";
import { Locale } from "common";
on(CORE.playerSpawnedEvent, (src: number, _charId: number) => {
notify(src, Locale("WELCOME_BACK"), "info");
});ai-core:playerUnloaded
Un personnage est libéré : le joueur a quitté le serveur, ou est revenu à l’écran des personnages. Se déclenche avant qu’ai-core abandonne le personnage, si bien que les exports d’ai-core répondent encore pour lui dans votre handler. Nettoyez ici tout ce que vous gardez par joueur.
Côté : Serveur · Constante : CORE.playerUnloadedEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
const activeJobs = new Map<number, string>();
on(CORE.playerUnloadedEvent, (src: number, _charId: number, reason: "dropped" | "switch") => {
activeJobs.delete(src);
console.log(`${src} unloaded (${reason})`);
});Avec reason = "switch", le même id serveur peut charger un autre personnage un instant plus tard. Indexez vos données par personnage avec charId ou effacez-les ici ; ne supposez jamais qu’un id serveur garde un seul personnage.
ai-core:moneyChanged
Le solde d’un compte d’un personnage chargé a changé. Se déclenche après l’application du changement, une fois par changement, seulement quand le solde a vraiment bougé.
Côté : Serveur · Constante : CORE.moneyChangedEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
// Signale au staff les gros paiements en liquide.
on(CORE.moneyChangedEvent, (src: number, account: string, balance: number, delta: number, reason: string) => {
if (account === "cash" && delta >= 100_000)
console.log(`${src} got $${delta} cash (${reason}), now $${balance}`);
});ai-core:jobsChanged
La liste des métiers d’un personnage chargé a changé : un métier ajouté ou retiré, ou un grade modifié.
Côté : Serveur · Constante : CORE.jobsChangedEvent
Arguments
Prop
Type
Écouteur
import { CORE, type JobMembership } from "@aicore-fivem/shared";
on(CORE.jobsChangedEvent, (src: number, jobs: JobMembership[]) => {
const police = jobs.find((m) => m.job === "police");
console.log(police ? `${src} is police grade ${police.grade}` : `${src} is not police`);
});ai-core:dutyChanged
Un personnage chargé a pris son service dans un métier, ou l’a quitté. Un joueur est en service dans au plus un métier à la fois.
Côté : Serveur · Constante : CORE.dutyChangedEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
on(CORE.dutyChangedEvent, (src: number, job: string | null) => {
console.log(job ? `${src} on duty: ${job}` : `${src} off duty`);
});Pour savoir combien de joueurs sont en service dans un métier, lisez la clé GlobalState ai:duty:<job> (voir State bags) au lieu de compter ces événements vous-même.
ai-core:gangsChanged
La liste des gangs d’un personnage chargé a changé : un gang ajouté ou retiré, ou un grade modifié.
Côté : Serveur · Constante : CORE.gangsChangedEvent
Arguments
Prop
Type
Écouteur
import { CORE, type GangMembership } from "@aicore-fivem/shared";
on(CORE.gangsChangedEvent, (src: number, gangs: GangMembership[]) => {
console.log(`${src} is in ${gangs.length} gang(s)`);
});ai-core:activeGangChanged
Un personnage chargé a changé le gang pour lequel il agit, ou n’agit plus pour aucun.
Côté : Serveur · Constante : CORE.activeGangChangedEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
on(CORE.activeGangChangedEvent, (src: number, gang: string | null) => {
console.log(`${src} now acts for ${gang ?? "no gang"}`);
});ai-core:metaChanged
Une valeur de métadonnées d’un personnage chargé a changé. Les métadonnées sont un sac libre de clés / valeurs stocké avec le personnage ; les ponts ESX / QB y gardent les métadonnées de framework (hunger, thirst, stress, isdead...).
Côté : Serveur · Constante : CORE.metaChangedEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
on(CORE.metaChangedEvent, (src: number, key: string, value: unknown) => {
if (key === "stress" && typeof value === "number" && value >= 90)
console.log(`${src} is very stressed`);
});ai-core:definitionsChanged
Un métier ou un gang a été ajouté, modifié ou supprimé dans le panneau d’administration. Se déclenche une fois par métier ou gang modifié.
Côté : Serveur · Constante : CORE.definitionsChangedEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
const labelCache = new Map<string, string>();
// Oublie un libellé en cache quand le panneau modifie ce métier.
on(CORE.definitionsChangedEvent, (file: "jobs" | "gangs", name: string) => {
if (file === "jobs") labelCache.delete(name);
});ai-core:characterScreen
L’écran des personnages d’un joueur se charge (après la connexion, ou après y être revenu). ai-core lit lui-même les apparences des cartes ; un script de vêtements écoute pour dessiner les portraits des cartes.
Côté : Serveur · Constante : CORE.characterScreenEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
on(CORE.characterScreenEvent, (src: number, charIds: number[]) => {
console.log(`${src} sees ${charIds.length} character card(s)`);
});ai-core:inventoryChanged
L’inventaire derrière la couche d’inventaire d’ai-core a changé : l’inventaire choisi a démarré ou s’est arrêté, ou le propriétaire en a choisi un autre dans le panneau. Oubliez tout ce que vous aviez mis en cache depuis l’ancien inventaire (libellés d’objets, définitions).
Côté : Serveur · Constante : CORE.inventoryChangedEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
let itemLabels: Record<string, string> | null = null;
on(CORE.inventoryChangedEvent, (resource: string | null) => {
itemLabels = null; // relire depuis le nouvel inventaire à la prochaine utilisation
console.log(`inventory is now ${resource ?? "none"}`);
});ai-core:itemUsed
Un joueur a utilisé un objet. Transporte les besoins que donne l’objet (faim, soif, stress), pour qu’un HUD ou un script de besoins les applique sans connaître l’inventaire. ai-hud l’écoute.
Côté : Serveur · Constante : CORE.itemUsedEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
on(CORE.itemUsedEvent, (src: number, name: string, status: Record<string, number> | null) => {
if (!status) return;
for (const [need, amount] of Object.entries(status))
console.log(`${src} used ${name}: ${need} ${amount > 0 ? "+" : ""}${amount}`);
});Aujourd’hui, seul ai-inventory signale les utilisations d’objets à ai-core : avec un autre inventaire, cet événement ne se déclenche pas. Écoutez cet événement, et non l’événement d’utilisation propre à un inventaire, pour que votre script fonctionne quand ai-inventory est l’inventaire et continue de fonctionner quand d’autres seront ajoutés.
ai-core:playerDied
Un joueur avec un personnage chargé est mort. ai-core le tient du propre rapport de mort de ped de FXServer (FXServer 38039 ou plus récent), si bien qu’aucun client n’est cru sur parole.
Côté : Serveur · Constante : CORE.playerDiedEvent
Arguments
Prop
Type
Écouteur
import { CORE } from "@aicore-fivem/shared";
on(CORE.playerDiedEvent, (src: number, killer: number | null, weaponHash: number) => {
if (killer !== null && killer !== src)
console.log(`${GetPlayerName(String(killer))} killed ${GetPlayerName(String(src))} (weapon ${weaponHash})`);
});Il s’agit de la mort dans le jeu, pas de l’état « à terre » du script de mort : un script de mort peut garder en vie un joueur à terre pour l’animer. Pour savoir si un joueur est à terre, utilisez medical de la lib serveur ou les exports médicaux serveur d’ai-core.
ai-core:vrp:config
Le propriétaire du serveur a modifié la correspondance vRP dans le panneau d’ai-core (onglet "vRP scripts"). Le pont vRP d’ai-core l’écoute ; vous n’en avez besoin que si vous lisez vous-même la correspondance vRP.
Côté : Serveur · Constante : VRP.configEvent
Arguments
Prop
Type
Écouteur
import { VRP, type VrpConfig } from "@aicore-fivem/shared";
on(VRP.configEvent, (config: VrpConfig) => {
console.log(`${config.permissions.length} vRP permission rule(s)`);
});Événements des autres scripts ai-*
Ceux-ci sont déclenchés par des scripts ai-*, pas par ai-core, mais beaucoup de ressources les écoutent. Leur référence complète se trouve sur la page développeur de chaque script.
ai-vehicles:owners
Les propriétaires des véhicules possédés en mémoire ont changé (un personnage chargé avec son garage, un véhicule acheté, vendu ou supprimé). Se déclenche au plus une fois par tick serveur avec tous les changements de ce tick. Les scripts de clés l’utilisent pour garder une table plaque vers propriétaire sans interroger ai-vehicles à chaque fois.
Côté : Serveur · Constante : VEHICLES_EVENTS.owners
Arguments
Prop
Type
Écouteur
import { resourceExport } from "@aicore-fivem/lib/server";
import { VEHICLES_EVENTS } from "@aicore-fivem/shared";
const owners = new Map<string, string>();
// Partir de la liste complète, puis suivre les changements.
for (const [plate, type, id] of resourceExport("ai-vehicles").GetPlateOwners()) owners.set(plate, `${type}:${id}`);
on(VEHICLES_EVENTS.owners, (puts: Array<[string, string, string]>, removes: string[]) => {
for (const [plate, type, id] of puts) owners.set(plate, `${type}:${id}`);
for (const plate of removes) owners.delete(plate);
});chatMessage
ai-chat déclenche l’événement FiveM classique chatMessage avant de livrer le message d’un joueur. Appeler CancelEvent() dans votre handler supprime le message.
Côté : Serveur · Constante : aucune (le nom propre à FiveM)
Arguments
Prop
Type
Écouteur
on("chatMessage", (source: number, _author: string, text: string) => {
if (text.toLowerCase().includes("discord.gg")) {
CancelEvent();
console.log(`blocked an invite link from ${source}`);
}
});Événements et état
Comment ai-core signale aux autres scripts qu’une chose a changé - événements locaux, événements réseau, state bags - et comment les écouter en TypeScript et en Lua.
Événements client
Chaque événement local côté client que déclenche ai-core - personnage local chargé ou déchargé, état à terre, valeurs en cache, visibilité du HUD, synchro du monde, définitions des métiers, aides de touches, ceinture de sécurité - avec arguments et écouteurs.