AI Core
Referência da APIEventos e estado

Eventos de servidor

Cada evento local de servidor que o ai-core dispara - personagens, dinheiro, empregos, serviço, gangues, metadata, definições, itens, mortes - com argumentos e listeners em TypeScript e Lua.

O ai-core dispara estes eventos no servidor com TriggerEvent (locais: outros recursos de servidor os ouvem, os clientes nunca). O espelho online da lib e as pontes ESX / QB / vRP são construídos sobre eles, então eles são o jeito mais barato de acompanhar os jogadores: nenhuma chamada de export, nenhuma consulta repetida.

O handler de cada evento roda de forma síncrona enquanto o ai-core está no meio da mudança: mantenha os handlers curtos e nunca espere dentro deles. Se precisar esperar (uma gravação no banco de dados), inicie-a sem bloquear.

ai-core:playerLoaded

O personagem de um jogador foi carregado e os dados dele enviados ao cliente. Dispara uma vez por carregamento de personagem, também depois de uma troca de personagem. Com a escolha de spawn ligada, dispara antes de o jogador escolher onde aparecer; ai-core:playerSpawned vem depois da escolha.

Lado: Servidor · Constante: CORE.playerLoadedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
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})`);
});

Os personagens já carregados antes de seu recurso iniciar nunca disparam isto para você. Use o onCharacter({ loaded }) da lib (aiLib.onCharacter em Lua), que os repete.

ai-core:playerSpawned

O personagem carregado foi colocado no mundo. Dispara logo depois de ai-core:playerLoaded, ou depois que o jogador escolheu um ponto de spawn quando o servidor deixa escolher. Use para coisas que precisam do ped no mundo (uma mensagem de boas-vindas, um teleporte).

Lado: Servidor · Constante: CORE.playerSpawnedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
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

Um personagem está sendo liberado: o jogador saiu do servidor ou voltou para a tela de personagens. Dispara antes de o ai-core descartar o personagem, então os exports do ai-core ainda respondem por ele dentro do seu handler. Limpe aqui tudo o que você guarda por jogador.

Lado: Servidor · Constante: CORE.playerUnloadedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
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})`);
});

Com reason = "switch" o mesmo id de servidor pode carregar outro personagem um momento depois. Indexe seus dados por personagem pelo charId ou limpe-os aqui; nunca suponha que um id de servidor mantém um só personagem.

ai-core:moneyChanged

O saldo de uma conta de um personagem carregado mudou. Dispara depois que a mudança é aplicada, uma vez por mudança, só quando o saldo realmente se moveu.

Lado: Servidor · Constante: CORE.moneyChangedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

// Sinaliza pagamentos grandes em dinheiro vivo para a staff.
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

A lista de empregos que um personagem carregado tem mudou: um emprego adicionado ou removido, ou um cargo mudou.

Lado: Servidor · Constante: CORE.jobsChangedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
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

Um personagem carregado entrou em serviço num emprego, ou saiu de serviço. Um jogador fica em serviço em no máximo um emprego de cada vez.

Lado: Servidor · Constante: CORE.dutyChangedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

on(CORE.dutyChangedEvent, (src: number, job: string | null) => {
  console.log(job ? `${src} on duty: ${job}` : `${src} off duty`);
});

Para saber quantos jogadores estão em serviço num emprego, leia o GlobalState ai:duty:<job> (veja State bags) em vez de contar estes eventos você mesmo.

ai-core:gangsChanged

A lista de gangues a que um personagem carregado pertence mudou: uma gangue adicionada ou removida, ou um cargo mudou.

Lado: Servidor · Constante: CORE.gangsChangedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
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

Um personagem carregado trocou a gangue em nome da qual age, ou agora não age por nenhuma.

Lado: Servidor · Constante: CORE.activeGangChangedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
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

Um valor de metadata de um personagem carregado mudou. Metadata é um saco livre de chave / valor gravado com o personagem; as pontes ESX / QB guardam ali a metadata do framework (fome, sede, estresse, isdead...).

Lado: Servidor · Constante: CORE.metaChangedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
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

Um emprego ou uma gangue foi adicionado, alterado ou apagado no painel de administração. Dispara uma vez por emprego ou gangue que mudou.

Lado: Servidor · Constante: CORE.definitionsChangedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

const labelCache = new Map<string, string>();

// Descarta um rótulo em cache quando o painel muda esse emprego.
on(CORE.definitionsChangedEvent, (file: "jobs" | "gangs", name: string) => {
  if (file === "jobs") labelCache.delete(name);
});

ai-core:characterScreen

A tela de personagens de um jogador está carregando (depois de entrar, ou depois de voltar a ela). O ai-core lê os visuais dos cards ele mesmo; um script de roupas escuta para desenhar retratos para os cards.

Lado: Servidor · Constante: CORE.characterScreenEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
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

O inventário por trás da camada de inventário do ai-core mudou: o inventário escolhido iniciou ou parou, ou o dono escolheu outro no painel. Descarte tudo o que você guardou em cache do inventário antigo (rótulos de itens, definições).

Lado: Servidor · Constante: CORE.inventoryChangedEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

let itemLabels: Record<string, string> | null = null;

on(CORE.inventoryChangedEvent, (resource: string | null) => {
  itemLabels = null; // lê de novo do novo inventário no próximo uso
  console.log(`inventory is now ${resource ?? "none"}`);
});

ai-core:itemUsed

Um jogador usou um item. Traz as necessidades que o item dá (fome, sede, estresse), para que um HUD ou script de necessidades as aplique sem conhecer o inventário. O ai-hud o escuta.

Lado: Servidor · Constante: CORE.itemUsedEvent

Argumentos

Prop

Type

Listener

resource/server/needs.ts
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}`);
});

Hoje só o ai-inventory informa usos de itens ao ai-core: com outro inventário este evento não dispara. Escute este evento, não o evento de uso próprio de um inventário, para que seu script funcione quando o ai-inventory é o inventário e continue funcionando quando outros forem adicionados.

ai-core:playerDied

Um jogador com um personagem carregado morreu. O ai-core pega isto do próprio relatório de morte de ped do FXServer (FXServer 38039 ou mais novo), então nenhum cliente é considerado confiável.

Lado: Servidor · Constante: CORE.playerDiedEvent

Argumentos

Prop

Type

Listener

resource/server/killfeed.ts
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})`);
});

Esta é a morte do jogo, não o estado de "caído" do script de morte: um script de morte pode manter vivo um jogador caído para animá-lo. Para "este jogador está caído", use o medical da lib de servidor ou os exports médicos de servidor do ai-core.

ai-core:vrp:config

O dono do servidor mudou o mapeamento vRP no painel do ai-core (aba "vRP scripts"). A ponte vRP do ai-core o escuta; você só precisa dele se lê o mapeamento vRP você mesmo.

Lado: Servidor · Constante: VRP.configEvent

Argumentos

Prop

Type

Listener

resource/server/index.ts
import { VRP, type VrpConfig } from "@aicore-fivem/shared";

on(VRP.configEvent, (config: VrpConfig) => {
  console.log(`${config.permissions.length} vRP permission rule(s)`);
});

Eventos de outros scripts ai-*

Estes são disparados por scripts ai-*, não pelo ai-core, mas muitos recursos os escutam. A referência completa deles está na página de desenvolvedor de cada script.

ai-vehicles:owners

Os donos dos veículos próprios em memória mudaram (um personagem carregou com a garagem dele, um veículo foi comprado, vendido ou apagado). Dispara no máximo uma vez por tick do servidor com cada mudança desse tick. Scripts de chaves o usam para manter um mapa de placa para dono sem perguntar ao ai-vehicles toda vez.

Lado: Servidor · Constante: VEHICLES_EVENTS.owners

Argumentos

Prop

Type

Listener

resource/server/owners.ts
import { resourceExport } from "@aicore-fivem/lib/server";
import { VEHICLES_EVENTS } from "@aicore-fivem/shared";

const owners = new Map<string, string>();

// Comece pela lista completa, depois siga as mudanças.
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

O ai-chat dispara o clássico evento chatMessage do FiveM antes de entregar a mensagem de um jogador. Chamar CancelEvent() no seu handler descarta a mensagem.

Lado: Servidor · Constante: nenhuma (o nome próprio do FiveM)

Argumentos

Prop

Type

Listener

resource/server/filter.ts
on("chatMessage", (source: number, _author: string, text: string) => {
  if (text.toLowerCase().includes("discord.gg")) {
    CancelEvent();
    console.log(`blocked an invite link from ${source}`);
  }
});

Nesta página