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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
on("chatMessage", (source: number, _author: string, text: string) => {
if (text.toLowerCase().includes("discord.gg")) {
CancelEvent();
console.log(`blocked an invite link from ${source}`);
}
});Eventos e estado
Como o ai-core avisa outros scripts de que algo mudou - eventos locais, net events, state bags - e como escutar em TypeScript e Lua.
Eventos de cliente
Cada evento local de cliente que o ai-core dispara - o personagem local carregado ou descarregado, estado de caído, valores em cache, visibilidade do HUD, sincronização do mundo, definições de empregos, dicas de teclas, cinto de segurança - com argumentos e listeners.