Членство и данные игрока
hasJob, inGang, onDutyIn, allows, onMembershipChange, getPlayerData, onPlayerData и seedPlayerData - персонаж, деньги, работы, дежурство и банды локального игрока в том виде, в каком их присылает ai-core.
ai-core отправляет собственные данные локального игрока на его клиент: один снимок при загрузке персонажа, затем только изменившиеся значения. Эти помощники читают эту копию, поэтому проверка стоит одного чтения из памяти и никогда не спрашивает сервер.
Используйте их для того, что игрок видит (canShow точки, пункт радиального меню, строка меню). Что игрок может делать, решает сервер по тем же данным (online на странице Игроки и персонажи): клиентская проверка никогда не является доказательством.
Данные игрока
Значения, которые хранит ai-core, по ключу (AiPlayerData):
Prop
Type
Типы членов: CharacterInfo, JobMembership и GangMembership.
getPlayerData
Последнее значение одного ключа. При первом использовании в вашем ресурсе также читает всё, что ai-core уже прислал (из экспорта ai-core GetPlayerData), поэтому ресурс, перезапущенный после загрузки игрока, сразу получает значения.
Сторона: Клиент · Ждёт: нет
getPlayerData<K extends keyof AiPlayerData>(key: K): AiPlayerData[K] | undefinedlocal value = aiLib.playerData.get(key)Параметры
Prop
Type
Возвращает
AiPlayerData[K] | undefined: значение или undefined (nil в Lua), если ещё ничего не пришло (персонаж не загружен, ai-core не запущен).
Пример
import { getPlayerData, notify } from "@aicore-fivem/lib/client";
RegisterCommand(
"whoami",
() => {
const character = getPlayerData("character");
const job = getPlayerData("job");
const cash = getPlayerData("money")?.cash ?? 0;
if (!character) return notify("No character loaded", "error");
notify(`${job?.job ?? "unemployed"} (${job?.grade ?? 0}), $${cash}`, "info");
},
false,
);onPlayerData
Запускает обработчик каждый раз, когда ai-core присылает ключ для этого игрока.
Сторона: Клиент · Ждёт: нет
onPlayerData<K extends keyof AiPlayerData>(key: K, handler: (value: AiPlayerData[K]) => void): () => voidaiLib.playerData.onChange(key, function(value) end)Параметры
Prop
Type
Возвращает
TypeScript: () => void, функция, которая удаляет обработчик. Lua ничего не возвращает.
Пример
import { onPlayerData } from "@aicore-fivem/lib/client";
const stop = onPlayerData("money", (money) => {
SendNUIMessage({ action: "money", data: { cash: money.cash ?? 0, bank: money.bank ?? 0 } });
});
// stop(), когда HUD закрывается насовсемЗначения, присланные до запуска вашего ресурса, обработчику не повторяются. Прочитайте текущее значение один раз через getPlayerData при старте, затем следите за изменениями через onPlayerData.
seedPlayerData
Заполняет значения вручную. Ключи, у которых уже есть значение, сохраняются. Вам это не нужно: lib сама заполняется из ai-core при первом использовании.
Сторона: Клиент · Ждёт: нет
seedPlayerData(data: Partial<AiPlayerData>): voidLua-аналога нет.
Параметры
Prop
Type
Возвращает
void.
Пример
import { seedPlayerData } from "@aicore-fivem/lib/client";
// Тестовая обвязка без ai-core.
seedPlayerData({ jobs: [{ job: "police", grade: 3 }], duty: "police" });Проверки членства
hasJob
Состоит ли игрок в одной из работ с минимальным рангом, на дежурстве или нет.
Сторона: Клиент · Ждёт: нет
hasJob(jobs: readonly string[], minGrade?: number): booleanLua-аналога нет: переберите aiLib.playerData.get('jobs') (см. пример на Lua для points.add).
Параметры
Prop
Type
Возвращает
boolean: true, если список пуст или игрок состоит в одной из jobs с рангом minGrade или выше.
Пример
import { hasJob, onMembershipChange, Points } from "@aicore-fivem/lib/client";
const points = new Points();
points.add("armory", {
coords: { x: 482.6, y: -995.2, z: 30.7 },
label: "Armory",
canShow: () => hasJob(["police", "sheriff"], 1),
onPressed: () => emitNet("mypolice:armory"),
});
onMembershipChange(() => points.refresh());inGang
Состоит ли игрок в одной из банд с минимальным рангом.
Сторона: Клиент · Ждёт: нет
inGang(gangs: readonly string[], minGrade?: number): booleanLua-аналога нет: переберите aiLib.playerData.get('gangs').
Параметры
Prop
Type
Возвращает
boolean: true, если список пуст или игрок состоит в одной из gangs с рангом minGrade или выше.
Пример
import { inGang, radial } from "@aicore-fivem/lib/client";
radial.add({
id: "mygang:stash",
label: "Gang stash",
icon: "box",
canShow: () => inGang(["ballas", "vagos"], 2),
onPressed: () => emitNet("mygang:stash"),
});onDutyIn
На дежурстве ли игрок в одной из работ.
Сторона: Клиент · Ждёт: нет
onDutyIn(jobs: readonly string[]): booleanLua-аналога нет: aiLib.playerData.get('duty') это работа на дежурстве.
Параметры
Prop
Type
Возвращает
boolean: true, если работа дежурства игрока входит в jobs.
Пример
import { onDutyIn, Points } from "@aicore-fivem/lib/client";
const points = new Points();
points.addVehicle("mymech:repair", {
label: "Repair",
icon: "wrench",
canShow: () => onDutyIn(["mechanic"]),
onPressed: (vehicle) => emitNet("mymech:repair", NetworkGetNetworkIdFromEntity(vehicle)),
});onMembershipChange
Выполняет функцию, когда меняются работы, дежурство или банды игрока. Используйте, чтобы обновлять точки и блипы, canShow которых их читает.
Сторона: Клиент · Ждёт: нет
onMembershipChange(fn: () => void): voidLua-аналога нет: aiLib.playerData.onChange для jobs, duty и gangs.
Параметры
Prop
Type
Возвращает
void.
Пример
import { onMembershipChange, Points, radial } from "@aicore-fivem/lib/client";
const points = new Points();
onMembershipChange(() => {
points.refresh();
radial.refresh();
});allows
Может ли локальный игрок пользоваться местом с правилом доступа. Серверный online.allows(source, rule) решает по тому же правилу, поэтому то, что видит игрок, в точности совпадает с тем, чем сервер позволяет пользоваться. Читайте правило из записи панели через readAccess(record) (@aicore-fivem/lib/shared).
Сторона: Клиент · Ждёт: нет
allows(rule: AccessRule): booleanLua-аналога нет.
Параметры
Prop
Type
AccessRule
Prop
Type
Тип: AccessRule.
Возвращает
boolean: true, если оба списка пусты (все); если игрок состоит в одной из gangs с её минимальным рангом; или если игрок состоит в одной из jobs с её минимальным рангом (и на дежурстве в ней при onDuty). Иначе false.
Пример
import { AdminWorld, allows, callAction, onMembershipChange, Points } from "@aicore-fivem/lib/client";
import { readAccess, readVec3, RecordObjects, type AccessRule } from "@aicore-fivem/lib/shared";
const world = new AdminWorld(["stashes"]);
const points = new Points();
interface Stash { coords: { x: number; y: number; z: number }; access: AccessRule }
const readStash = (_key: string, raw: Record<string, unknown>): Stash | null => {
const coords = readVec3(raw.coords);
return coords ? { coords, access: readAccess(raw) } : null;
};
new RecordObjects(world, "stashes", readStash, (id, stash) => {
points.add(id, {
coords: stash.coords,
label: "Stash",
canShow: () => allows(stash.access),
onPressed: () => callAction("mystash:open", [id], { fallback: "STASH_FAILED" }),
});
return () => points.remove(id);
});
onMembershipChange(() => points.refresh());Камера и время
ScriptCamera, TickLoop, AreaFollower и ServerClock - скриптовые камеры, покадровые задачи, которые работают только когда нужны, сообщение серверу об области игрока и часы сервера на клиенте.
Lib: сервер
@aicore-fivem/lib/server и серверная сторона aiLib: что это такое, как загружать их в TypeScript и Lua, и все тематические страницы.