Scheduling und Lebenszyklus
every, onStop, caller, ByResource, Reasons, sleep und waitFor: periodische Arbeit, Warten und Daten, die der Ressource gehören, die sie registriert hat.
import { every, onStop, caller, ByResource, Reasons } from "@aicore-fivem/lib/fivem";
import { sleep, waitFor } from "@aicore-fivem/lib/shared";Periodische Arbeit
every
Führt eine Funktion alle ms Millisekunden aus (0 = jeden Frame), aus dem einzigen Scheduler deiner Ressource. Nutze es statt setInterval, setTick oder einer CreateThread-Schleife mit Wait: Alle Jobs einer Ressource teilen sich einen Tick, und dieser Tick existiert nur, solange mindestens ein Job eingeschaltet ist, daher kostet eine untätige Ressource in resmon nichts.
Seite: Client und Server · Wartet: nein
every(ms: number, fn: () => unknown, options?: EveryOptions): Joblocal job = aiLib.every(ms, fn, options) -- job:set(active), job:stop(), job.runningParameter
Prop
Type
EveryOptions
Prop
Type
Rückgabewert
Job: ein Handle, um den Job ein- und auszuschalten.
Prop
Type
Beispiel
Ein Job pro Frame, der nur läuft, solange er etwas zu tun hat:
import { every, cache, onCache } from "@aicore-fivem/lib/client";
// Blendet das Fadenkreuz in jedem Frame aus, aber nur, solange eine Waffe in der Hand ist.
const hideCrosshair = every(0, () => HideHudComponentThisFrame(14), {
active: cache.weapon !== false,
name: "hide crosshair",
});
onCache("weapon", (weapon) => hideCrosshair.set(weapon !== false));Ein Job darf nie warten: kein Wait in Lua, keine lange await-Kette in TypeScript, von der du erwartest, dass sie vor dem nächsten Lauf fertig ist. In Lua hält ein Wait in einem Job jeden anderen Job der Ressource auf; starte dafür aus dem Job einen Thread. Ein fehlschlagender Job wird höchstens einmal alle 10 Sekunden geloggt (die Fehler dazwischen werden in die nächste Zeile mitgezählt).
Warten
sleep
Wartet ms Millisekunden.
Seite: Client, Server und NUI · Wartet: ja (Promise)
sleep(ms: number): Promise<void>Lua: kein Zwilling; nutze Wait(ms) innerhalb eines Threads.
Parameter
Prop
Type
Rückgabewert
Promise<void>, das nach ms Millisekunden erfüllt wird.
Beispiel
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
Prüft eine Bedingung, bis sie einen Wert liefert, und gibt dann diesen Wert zurück. Nutze es, um auf etwas zu warten, das das Spiel in seinem eigenen Tempo tut: eine Entity, die existieren soll, ein Modell, das laden soll, ein Wert, der ankommen soll.
Seite: Client, Server und NUI · Wartet: ja (Promise in TypeScript, hält in Lua den Thread an)
waitFor<T>(check: () => T | undefined, timeoutMs?: number | false, intervalMs?: number): Promise<T>local value = aiLib.waitFor(check, timeout, interval) -- Wert, oder nil nach dem Timeout; innerhalb eines Threads aufrufenParameter
Prop
Type
Rückgabewert
TypeScript: Promise<T>, das mit dem ersten Wert erfüllt wird, den check zurückgegeben hat und der nicht undefined war. Es wird nach dem Timeout mit Error("waitFor timed out after <ms> ms") abgelehnt.
Lua: der Wert, oder nil nach dem Timeout (es wirft nicht).
Beispiel
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; // nicht innerhalb von 5 Sekunden gestreamt
}
}Behandle in TypeScript immer die Ablehnung (try / catch oder .catch()) oder übergib false als Timeout. In Lua funktioniert waitFor nur innerhalb eines Threads.
Lebenszyklus der Ressource
onStop
Führt eine Funktion aus, wenn deine Ressource stoppt (auf der Seite, auf der der Code läuft). Nutze es, um zu löschen, was Natives erstellt haben und sonst nichts entfernt: Entities, die du gespawnt hast, Kameras, einen NUI-Fokus.
Seite: Client und Server · Wartet: nein
onStop(fn: () => void): voidLua: kein Zwilling; nutze AddEventHandler('onResourceStop', function(name) if name == GetCurrentResourceName() then ... end end).
Parameter
Prop
Type
Rückgabewert
void.
Beispiel
import { onStop } from "@aicore-fivem/lib/server";
const spawned = new Set<number>();
onStop(() => {
for (const entity of spawned) if (DoesEntityExist(entity)) DeleteEntity(entity);
});Alle onStop, ByResource und Reasons einer Ressource teilen sich einen Stopp-Listener, daher kosten viele davon nichts extra.
caller
Der Name der Ressource, die den gerade laufenden Export aufgerufen hat. In deinem eigenen Code (nicht in einem Export-Aufruf) ist es der Name deiner Ressource.
Seite: Client und Server · Wartet: nein
caller(): stringLua: kein Zwilling; nutze GetInvokingResource() or GetCurrentResourceName().
Rückgabewert
string: der Name der aufrufenden Ressource, oder der Name dieser Ressource, wenn keine andere Ressource aufruft.
Beispiel
import { registerExport, caller } from "@aicore-fivem/lib/server";
registerExport("Ping", () => {
console.log(`${caller()} asked for a ping`);
return true;
});ByResource
Eine Map, deren Einträge der Ressource gehören, die sie gesetzt hat. Wenn diese Ressource stoppt, werden ihre Einträge sofort entfernt (und onDrop läuft für jeden). Nutze sie für Dinge, die andere Ressourcen über deine Exports registrieren: Hooks, Prompts, Items, Menüeinträge.
Seite: Client und Server · Wartet: nein
new ByResource<K, V>(options?: { onDrop?: (resource: string, key: K, value: V) => void })Lua: kein Zwilling.
Parameter
Prop
Type
Methoden
Prop
Type
Beispiel
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`),
});
// Eine andere Ressource: 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 = die Ressource, die AddHook aufruft
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
Ein Schalter, der an ist, solange mindestens ein Grund gesetzt ist. Jede Ressource setzt ihre eigenen benannten Gründe, und die Gründe einer stoppenden Ressource werden gelöscht. Nutze es für „das HUD ausblenden“, „die Synchronisation pausieren“, „das Menü sperren“: Mehrere Skripte können gleichzeitig fragen, und der Zustand springt erst zurück, wenn der letzte loslässt.
Seite: Client und Server · Wartet: nein
new Reasons()Lua: kein Zwilling.
Methoden
Prop
Type
Beispiel
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 }));
// Andere Ressourcen: exports["my-hud"].Hide("cutscene") und 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);
});Exports zwischen Ressourcen
registerExport, resourceExport, optionalExport, callExport, provideExport und isResourceStarted: Exports aus TypeScript anbieten und aufrufen.
State Bags
EntityState, PlayerState, GlobalKey, GlobalGroup und die Parser stateNumber, stateBoolean, stateString: replizierte Werte aus dem Speicher lesen.