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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
on("chatMessage", (source: number, _author: string, text: string) => {
if (text.toLowerCase().includes("discord.gg")) {
CancelEvent();
console.log(`blocked an invite link from ${source}`);
}
});Zdarzenia i stan
Jak ai-core mówi innym skryptom, że coś się zmieniło - zdarzenia lokalne, zdarzenia sieciowe, state bagi - i jak ich nasłuchiwać w TypeScript i Lua.
Zdarzenia klienckie
Każde klienckie zdarzenie lokalne wysyłane przez ai-core - wczytanie lub zwolnienie lokalnej postaci, stan powalenia, wartości w pamięci podręcznej, widoczność HUD, synchronizacja świata, definicje prac, podpowiedzi klawiszy, pas bezpieczeństwa - z argumentami i nasłuchiwaniem.