Harmonogram i cykl życia
every, onStop, caller, ByResource, Reasons, sleep i waitFor: praca okresowa, czekanie i dane należące do zasobu, który je zarejestrował.
import { every, onStop, caller, ByResource, Reasons } from "@aicore-fivem/lib/fivem";
import { sleep, waitFor } from "@aicore-fivem/lib/shared";Praca okresowa
every
Uruchamia funkcję co ms milisekund (0 = co klatkę) z jedynego harmonogramu twojego zasobu. Używaj jej zamiast setInterval, setTick albo pętli CreateThread z Wait: wszystkie zadania zasobu dzielą jeden tick, a ten tick istnieje tylko wtedy, gdy co najmniej jedno zadanie jest włączone, więc bezczynny zasób nic nie kosztuje w resmonie.
Strona: Klient i serwer · Czeka: nie
every(ms: number, fn: () => unknown, options?: EveryOptions): Joblocal job = aiLib.every(ms, fn, options) -- job:set(active), job:stop(), job.runningParametry
Prop
Type
EveryOptions
Prop
Type
Zwracana wartość
Job: uchwyt do włączania i wyłączania zadania.
Prop
Type
Przykład
Zadanie na każdą klatkę, które działa tylko wtedy, gdy ma coś do zrobienia:
import { every, cache, onCache } from "@aicore-fivem/lib/client";
// Ukrywa celownik co klatkę, ale tylko gdy broń jest w ręku.
const hideCrosshair = every(0, () => HideHudComponentThisFrame(14), {
active: cache.weapon !== false,
name: "hide crosshair",
});
onCache("weapon", (weapon) => hideCrosshair.set(weapon !== false));Zadanie nigdy nie może czekać: żadnego Wait w Lua, żadnego długiego łańcucha await w TypeScript, który ma się skończyć przed następnym uruchomieniem. W Lua Wait wewnątrz zadania wstrzymuje każde inne zadanie zasobu; do tego uruchom wątek z zadania. Błędne zadanie jest logowane najwyżej raz na 10 sekund (błędy pomiędzy są doliczane do następnej linii).
Czekanie
sleep
Czeka ms milisekund.
Strona: Klient, serwer i NUI · Czeka: tak (Promise)
sleep(ms: number): Promise<void>Lua: brak odpowiednika; użyj Wait(ms) wewnątrz wątku.
Parametry
Prop
Type
Zwracana wartość
Promise<void>, który się rozwiązuje po ms milisekundach.
Przykład
import { sleep } from "@aicore-fivem/lib/shared";
import { fadeOut, fadeIn } from "@aicore-fivem/lib/client";
async function blink(): Promise<void> {
await fadeOut(300);
await sleep(1000);
await fadeIn(300);
}waitFor
Sprawdza warunek, aż da on wartość, potem zwraca tę wartość. Używaj jej, żeby czekać na coś, co gra robi we własnym tempie: aż encja zacznie istnieć, model się wczyta, wartość przyjdzie.
Strona: Klient, serwer i NUI · Czeka: tak (Promise w TypeScript, w Lua wstrzymuje wątek)
waitFor<T>(check: () => T | undefined, timeoutMs?: number | false, intervalMs?: number): Promise<T>local value = aiLib.waitFor(check, timeout, interval) -- wartość albo nil po upływie limitu czasu; wywołuj wewnątrz wątkuParametry
Prop
Type
Zwracana wartość
TypeScript: Promise<T>, który się rozwiązuje pierwszą wartością zwróconą przez check, która nie była undefined. Po upływie limitu czasu odrzuca z Error("waitFor timed out after <ms> ms").
Lua: wartość albo nil po upływie limitu czasu (nie rzuca wyjątku).
Przykład
import { waitFor } from "@aicore-fivem/lib/shared";
async function vehicleFromNet(netId: number): Promise<number | null> {
try {
return await waitFor(() => {
const vehicle = NetworkGetEntityFromNetworkId(netId);
return DoesEntityExist(vehicle) ? vehicle : undefined;
}, 5000);
} catch {
return null; // nie wczytał się w ciągu 5 sekund
}
}W TypeScript zawsze obsłuż odrzucenie (try / catch albo .catch()) albo podaj false jako limit czasu. W Lua waitFor działa tylko wewnątrz wątku.
Cykl życia zasobu
onStop
Uruchamia funkcję, gdy twój zasób się zatrzymuje (po stronie, na której działa kod). Używaj jej do usuwania tego, co stworzyły natywki, a czego nic innego nie usuwa: zespawnowanych encji, kamer, fokusu NUI.
Strona: Klient i serwer · Czeka: nie
onStop(fn: () => void): voidLua: brak odpowiednika; użyj AddEventHandler('onResourceStop', function(name) if name == GetCurrentResourceName() then ... end end).
Parametry
Prop
Type
Zwracana wartość
void.
Przykład
import { onStop } from "@aicore-fivem/lib/server";
const spawned = new Set<number>();
onStop(() => {
for (const entity of spawned) if (DoesEntityExist(entity)) DeleteEntity(entity);
});Wszystkie onStop, ByResource i Reasons zasobu dzielą jeden listener zatrzymania, więc dodanie wielu nic dodatkowo nie kosztuje.
caller
Nazwa zasobu, który wywołał aktualnie działający eksport. W twoim własnym kodzie (nie w wywołaniu eksportu) to nazwa twojego zasobu.
Strona: Klient i serwer · Czeka: nie
caller(): stringLua: brak odpowiednika; użyj GetInvokingResource() or GetCurrentResourceName().
Zwracana wartość
string: nazwa wywołującego zasobu albo nazwa tego zasobu, gdy żaden inny zasób nie wywołuje.
Przykład
import { registerExport, caller } from "@aicore-fivem/lib/server";
registerExport("Ping", () => {
console.log(`${caller()} asked for a ping`);
return true;
});ByResource
Mapa, której wpisy należą do zasobu, który je ustawił. Gdy ten zasób się zatrzymuje, jego wpisy są od razu usuwane (a onDrop działa dla każdego z nich). Używaj jej do rzeczy, które inne zasoby rejestrują przez twoje eksporty: hooki, prompty, przedmioty, pozycje menu.
Strona: Klient i serwer · Czeka: nie
new ByResource<K, V>(options?: { onDrop?: (resource: string, key: K, value: V) => void })Lua: brak odpowiednika.
Parametry
Prop
Type
Metody
Prop
Type
Przykład
import { ByResource, registerExport } from "@aicore-fivem/lib/server";
import { readText } from "@aicore-fivem/lib/shared";
type Hook = (source: number, text: string) => boolean;
const hooks = new ByResource<string, Hook>({
onDrop: (resource, id) => console.log(`${resource} stopped: hook ${id} removed`),
});
// Inny zasób: exports["my-chat"].AddHook("swear-filter", (source, text) => ...)
registerExport("AddHook", (id: unknown, hook: unknown) => {
const name = readText(id, 64);
if (name === null || typeof hook !== "function") return false;
hooks.set(name, hook as Hook); // owner = zasób, który wywołuje AddHook
return true;
});
export function allowed(source: number, text: string): boolean {
for (const hook of hooks.values()) if (!hook(source, text)) return false;
return true;
}Reasons
Przełącznik, który jest włączony, dopóki ustawiony jest co najmniej jeden powód. Każdy zasób ustawia własne nazwane powody, a powody zatrzymywanego zasobu są czyszczone. Używaj go do "ukryj HUD", "wstrzymaj synchronizację", "zablokuj menu": kilka skryptów może prosić naraz, a stan wraca dopiero wtedy, gdy ostatni z nich odpuści.
Strona: Klient i serwer · Czeka: nie
new Reasons()Lua: brak odpowiednika.
Metody
Prop
Type
Przykład
import { Reasons, registerExport } from "@aicore-fivem/lib/client";
import { readText } from "@aicore-fivem/lib/shared";
const hidden = new Reasons();
hidden.onChange((any) => SendNUIMessage({ action: "visible", value: !any }));
// Inne zasoby: exports["my-hud"].Hide("cutscene") i exports["my-hud"].Show("cutscene")
registerExport("Hide", (reason: unknown) => {
const name = readText(reason, 64);
if (name !== null) hidden.set(name, true);
});
registerExport("Show", (reason: unknown) => {
const name = readText(reason, 64);
if (name !== null) hidden.set(name, false);
});Eksporty między zasobami
registerExport, resourceExport, optionalExport, callExport, provideExport i isResourceStarted: udostępnianie i wywoływanie eksportów z TypeScript.
State bagi
EntityState, PlayerState, GlobalKey, GlobalGroup i parsery stateNumber, stateBoolean, stateString: odczyt replikowanych wartości z pamięci.