AI Core
Dokumentacja APIZdarzenia i stan

Zdarzenia serwerowe

Każde serwerowe zdarzenie lokalne wysyłane przez ai-core - postacie, pieniądze, prace, służba, gangi, metadane, definicje, przedmioty, śmierci - z argumentami i nasłuchiwaniem w TypeScript i Lua.

ai-core wysyła te zdarzenia na serwerze przez TriggerEvent (lokalnie: słyszą je inne zasoby serwerowe, klienci nigdy). Lustro online liba i mosty ESX / QB / vRP są na nich zbudowane, więc to najtańszy sposób śledzenia graczy: bez wywołań eksportów, bez odpytywania.

Handler każdego zdarzenia działa synchronicznie, gdy ai-core jest w trakcie zmiany: trzymaj handlery krótkie i nigdy w nich nie czekaj. Jeśli musisz czekać (zapis do bazy danych), uruchom to bez blokowania.

ai-core:playerLoaded

Postać gracza została wczytana, a jej dane wysłane do jego klienta. Wysyłane raz na wczytanie postaci, także po zmianie postaci. Przy włączonym wyborze miejsca pojawienia się jest wysyłane, zanim gracz wybierze, gdzie się pojawić; ai-core:playerSpawned następuje po wyborze.

Strona: Serwer · Stała: CORE.playerLoadedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Postacie wczytane, zanim twój zasób wystartował, nigdy nie wyślą tego dla ciebie. Używaj onCharacter({ loaded }) z liba (aiLib.onCharacter w Lua), które je odtwarza.

ai-core:playerSpawned

Wczytana postać została umieszczona w świecie. Wysyłane zaraz po ai-core:playerLoaded albo po tym, jak gracz wybrał miejsce pojawienia się, gdy serwer pozwala wybierać. Używaj tego do rzeczy, które potrzebują peda w świecie (wiadomość powitalna, teleport).

Strona: Serwer · Stała: CORE.playerSpawnedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Postać jest zwalniana: gracz opuścił serwer albo wrócił do ekranu postaci. Wysyłane zanim ai-core zwolni postać, więc eksporty ai-core nadal na nią odpowiadają wewnątrz twojego handlera. Tutaj sprzątaj wszystko, co trzymasz per gracz.

Strona: Serwer · Stała: CORE.playerUnloadedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Przy reason = "switch" to samo id serwera może chwilę później wczytać inną postać. Kluczuj dane per postać po charId albo czyść je tutaj; nigdy nie zakładaj, że id serwera zachowuje jedną postać.

ai-core:moneyChanged

Zmieniło się saldo konta wczytanej postaci. Wysyłane po zastosowaniu zmiany, raz na zmianę, tylko gdy saldo naprawdę się przesunęło.

Strona: Serwer · Stała: CORE.moneyChangedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

// Oznacza duże płatności gotówką dla obsługi.
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

Zmieniła się lista prac wczytanej postaci: praca dodana lub usunięta albo zmiana stopnia.

Strona: Serwer · Stała: CORE.jobsChangedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Wczytana postać weszła na służbę w pracy albo z niej zeszła. Gracz jest na służbie najwyżej w jednej pracy naraz.

Strona: Serwer · Stała: CORE.dutyChangedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Aby wiedzieć, ilu graczy jest na służbie w pracy, czytaj GlobalState ai:duty:<job> (zobacz State bagi) zamiast samemu liczyć te zdarzenia.

ai-core:gangsChanged

Zmieniła się lista gangów, do których należy wczytana postać: gang dodany lub usunięty albo zmiana stopnia.

Strona: Serwer · Stała: CORE.gangsChangedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Wczytana postać zmieniła gang, w imieniu którego działa, albo teraz nie działa w imieniu żadnego.

Strona: Serwer · Stała: CORE.activeGangChangedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Zmieniła się wartość metadanych wczytanej postaci. Metadane to dowolny worek klucz / wartość zapisywany z postacią; mosty ESX / QB trzymają tam metadane frameworka (głód, pragnienie, stres, isdead...).

Strona: Serwer · Stała: CORE.metaChangedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Praca lub gang zostały dodane, zmienione lub usunięte w panelu administratora. Wysyłane raz na każdą zmienioną pracę lub gang.

Strona: Serwer · Stała: CORE.definitionsChangedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

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

// Usuń etykietę z pamięci podręcznej, gdy panel zmieni tę pracę.
on(CORE.definitionsChangedEvent, (file: "jobs" | "gangs", name: string) => {
  if (file === "jobs") labelCache.delete(name);
});

ai-core:characterScreen

Ekran postaci gracza się wczytuje (po dołączeniu albo po powrocie do niego). ai-core sam czyta wyglądy kart; skrypt ubrań nasłuchuje, aby narysować portrety dla kart.

Strona: Serwer · Stała: CORE.characterScreenEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Zmienił się ekwipunek za warstwą ekwipunku ai-core: wybrany ekwipunek wystartował lub się zatrzymał albo właściciel wybrał inny w panelu. Usuń wszystko, co zapamiętałeś ze starego ekwipunku (etykiety przedmiotów, definicje).

Strona: Serwer · Stała: CORE.inventoryChangedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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; // odczytaj ponownie z nowego ekwipunku przy następnym użyciu
  console.log(`inventory is now ${resource ?? "none"}`);
});

ai-core:itemUsed

Gracz użył przedmiotu. Niesie potrzeby, które daje przedmiot (głód, pragnienie, stres), więc HUD lub skrypt potrzeb stosuje je bez znajomości ekwipunku. Nasłuchuje tego ai-hud.

Strona: Serwer · Stała: CORE.itemUsedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Obecnie tylko ai-inventory zgłasza ai-core użycia przedmiotów: przy innym ekwipunku to zdarzenie nie jest wysyłane. Nasłuchuj tego zdarzenia, a nie własnego zdarzenia użycia ekwipunku, aby twój skrypt działał, gdy ekwipunkiem jest ai-inventory, i działał dalej, gdy zostaną dodane inne.

ai-core:playerDied

Gracz z wczytaną postacią zginął. ai-core bierze to z własnego raportu śmierci peda w FXServer (FXServer 38039 lub nowszy), więc żaden klient nie jest obdarzany zaufaniem.

Strona: Serwer · Stała: CORE.playerDiedEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

To śmierć w grze, a nie stan "powalony" skryptu śmierci: skrypt śmierci może utrzymywać powalonego gracza przy życiu, aby go animować. Dla "czy ten gracz jest powalony" używaj medical z serwerowego liba albo serwerowych eksportów leczenia ai-core.

ai-core:vrp:config

Właściciel serwera zmienił mapowanie vRP w panelu ai-core (karta "vRP scripts"). Nasłuchuje tego most vRP ai-core; potrzebujesz tego tylko wtedy, gdy sam czytasz mapowanie vRP.

Strona: Serwer · Stała: VRP.configEvent

Argumenty

Prop

Type

Nasłuchiwanie

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

Zdarzenia innych skryptów ai-*

Wysyłają je skrypty ai-*, nie ai-core, ale nasłuchuje ich wiele zasobów. Ich pełna dokumentacja jest na stronie developera każdego skryptu.

ai-vehicles:owners

Zmienili się właściciele posiadanych pojazdów w pamięci (postać wczytana ze swoim garażem, pojazd kupiony, sprzedany lub usunięty). Wysyłane najwyżej raz na tick serwera z każdą zmianą z tego ticku. Skrypty kluczy używają tego, aby trzymać mapę tablica na właściciela bez pytania ai-vehicles za każdym razem.

Strona: Serwer · Stała: VEHICLES_EVENTS.owners

Argumenty

Prop

Type

Nasłuchiwanie

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

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

// Zacznij od pełnej listy, potem śledź zmiany.
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 wysyła klasyczne zdarzenie FiveM chatMessage, zanim dostarczy wiadomość gracza. Wywołanie CancelEvent() w twoim handlerze odrzuca wiadomość.

Strona: Serwer · Stała: brak (własna nazwa FiveM)

Argumenty

Prop

Type

Nasłuchiwanie

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

Na tej stronie