AI Core
Справочник APIAI Core: серверные экспорты

Персонажи и игроки

Прочитать данные и персонажа загруженного игрока, найти игрока по id персонажа или citizen id, сменить персонажа, переместить офлайн-персонажа, игроки в зоне видимости.

Игрок - это подключённый человек с серверным id (source). Персонаж - один из людей, которыми играет этот игрок; у него есть id в базе данных (charId) и citizen id (citizenid, короткий текст вроде ABC12345). У игрока появляется загруженный персонаж после выбора на экране персонажей. Большинство экспортов здесь до этого отвечают null.

Вызовы экспортов копируют свой ответ, поэтому прочитайте нужное один раз и следите за событиями ai-core (ai-core:playerLoaded, ai-core:playerUnloaded), а не спрашивайте снова. См. События и состояние.

GetPlayerData

Всё, что ai-core хранит для загруженного игрока, одним объектом: персонаж, деньги, работы, дежурство, банды и метаданные. Используйте, когда ресурс стартует поздно и ему один раз нужно полное состояние игрока; для отдельных значений используйте экспорты поменьше ниже.

Сторона: сервер · Ожидание: нет · Библиотека: нет на сервере (getPlayerData из клиентской библиотеки читает те же данные в игре игрока)

Сигнатура
GetPlayerData(src: number): AiPlayerData | null
Lua
local data = exports['ai-core']:GetPlayerData(source) -- table или nil

Параметры

Prop

Type

Возвращает

AiPlayerData | null: копия данных игрока (AiPlayerData). null, когда ни у кого с этим серверным id нет загруженного персонажа (не подключён или ещё на экране персонажей). Копия потом не меняется: вызовите снова или следите за событиями, чтобы получить новые значения.

Пример

import { addCommand, resourceExport } from "@aicore-fivem/lib/server";

const core = resourceExport("ai-core");

addCommand("whoami", { help: "Shows your character", restricted: true }, (source) => {
  const data = core.GetPlayerData(source);
  if (!data?.character) return;
  const { firstname, lastname } = data.character;
  console.log(`${firstname} ${lastname}: job ${data.job.job} (grade ${data.job.grade}), cash ${data.money.cash ?? 0}`);
});

Весь объект копируется при каждом вызове. Никогда не вызывайте его в цикле по всем игрокам или по таймеру: читайте отдельные значения (GetMoney, GetDutyJob) или используйте зеркало online из библиотеки.

GetCharacter

Загруженный персонаж игрока: id в базе данных, citizen id, слот, имена, дата рождения, пол и национальность. Используйте, чтобы показать имя или сохранить что-то по id персонажа.

Сторона: сервер · Ожидание: нет · Библиотека: нет (online.character(source) читает то же из зеркала библиотеки без вызова экспорта)

Сигнатура
GetCharacter(src: number): CharacterInfo | null
Lua
local character = exports['ai-core']:GetCharacter(source) -- table или nil

Параметры

Prop

Type

Возвращает

CharacterInfo | null: персонаж (CharacterInfo). null, когда у игрока нет загруженного персонажа.

Пример

import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";

const core = resourceExport("ai-core");

onClientCallback("myscript:profile", (source) => {
  const character = core.GetCharacter(source);
  if (!character) return fail("NO_CHARACTER");
  return { ok: true, name: `${character.firstname} ${character.lastname}`, citizenid: character.citizenid };
});

GetSourceByCharId

Серверный id игрока, который играет персонажем прямо сейчас. Используйте, когда вы сохранили id персонажа (владелец, контакт) и нужно найти этого человека в игре.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetSourceByCharId(charId: number): number | null
Lua
local src = exports['ai-core']:GetSourceByCharId(charId) -- number или nil

Параметры

Prop

Type

Возвращает

number | null: серверный id игрока. null, когда этим персонажем сейчас никто не играет (офлайн или загружен другой персонаж).

Пример

import { notify, resourceExport } from "@aicore-fivem/lib/server";
import { Locale } from "common";

const core = resourceExport("ai-core");

/** Tells a house owner that someone rang, when the owner is online. */
export function ringOwner(ownerCharId: number): void {
  const owner = core.GetSourceByCharId(ownerCharId);
  if (owner !== null) notify(owner, Locale("NOTIFY_DOORBELL"), "info");
}

GetSourceByCitizenId

То же, что GetSourceByCharId, но по citizen id. Используйте с данными, которые хранят citizen id (так делает большинство таблиц в стиле ESX / QB).

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetSourceByCitizenId(citizenid: string): number | null
Lua
local src = exports['ai-core']:GetSourceByCitizenId(citizenid) -- number или nil

Параметры

Prop

Type

Возвращает

number | null: серверный id игрока, который играет этим персонажем. null, когда персонаж не загружен.

Пример

import { addCommand, resourceExport } from "@aicore-fivem/lib/server";

const core = resourceExport("ai-core");

addCommand("findcid", {
  help: "Finds the player of a citizen id",
  params: [{ name: "citizenid", type: "string" }],
  restricted: true,
}, (source, args) => {
  const target = core.GetSourceByCitizenId(args.citizenid);
  console.log(target === null ? "not online" : `server id ${target}`);
});

GetLoadedSources

Серверные id всех игроков с загруженным персонажем. Используйте для редкой работы по всему серверу (предупреждение о перезапуске, список для админа).

Сторона: сервер · Ожидание: нет · Библиотека: online.sources() читает то же из зеркала библиотеки

Сигнатура
GetLoadedSources(): number[]
Lua
local sources = exports['ai-core']:GetLoadedSources() -- список чисел

Параметры

Нет.

Возвращает

number[]: по серверному id на каждого загруженного игрока, без определённого порядка. Пустой список, когда ни у кого нет загруженного персонажа. Игроков, которые ещё на экране персонажей, в нём нет.

Пример

import { addCommand, notify, resourceExport } from "@aicore-fivem/lib/server";
import { Locale } from "common";

const core = resourceExport("ai-core");

addCommand("announce", {
  help: "Sends a notification to every player",
  params: [{ name: "text", type: "longString" }],
  restricted: true,
}, (_source, args) => {
  for (const target of core.GetLoadedSources())
    notify(target, Locale("NOTIFY_ANNOUNCEMENT", args.text), "warning");
});

Никогда не вызывайте другой экспорт для каждого id из этого списка на частом пути (GetLoadedSources() + GetDutyJob на каждого игрока каждую секунду). Кто на дежурстве, имена и работы многих игроков берутся из зеркала online в библиотеке; кто рядом - из playersNear.

GetUserId

Id аккаунта подключённого игрока: строка в ai_core_users, которая хранит аккаунт FiveM игрока и всех его персонажей. В отличие от большинства экспортов отвечает и тогда, когда игрок ещё на экране персонажей.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetUserId(src: number): number | null
Lua
local userId = exports['ai-core']:GetUserId(source) -- number или nil

Параметры

Prop

Type

Возвращает

number | null: id аккаунта. null, когда игрок не подключён или ещё не дошёл до экрана персонажей.

Пример

import { addCommand, resourceExport } from "@aicore-fivem/lib/server";

const core = resourceExport("ai-core");

addCommand("account", {
  help: "Shows a player account id",
  params: [{ name: "id", type: "playerId" }],
  restricted: true,
}, (_source, args) => {
  console.log(`account ${core.GetUserId(args.id) ?? "unknown"}`);
});

GetFivemId

Id аккаунта FiveM (Cfx.re) игрока. ai-core использует его как ключ аккаунта игрока: игрок без него не может подключиться.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetFivemId(src: number): string | null
Lua
local fivemId = exports['ai-core']:GetFivemId(source) -- string или nil

Параметры

Prop

Type

Возвращает

string | null: id без префикса fivem: (например, 1234567). null, когда у игрока нет загруженного персонажа.

Пример

import { addCommand, resourceExport } from "@aicore-fivem/lib/server";

const core = resourceExport("ai-core");

addCommand("fivemid", {
  help: "Prints the add_principal line for a player",
  params: [{ name: "id", type: "playerId" }],
  restricted: true,
}, (_source, args) => {
  const id = core.GetFivemId(args.id);
  if (id) console.log(`add_principal identifier.fivem:${id} group.admin`);
});

GetCharacterInfo

Персонаж по id в базе данных, загружен он или нет, с id аккаунта, которому он принадлежит. Используйте, чтобы показать владельца чего-либо, когда этот человек может быть офлайн.

Сторона: сервер · Ожидание: нет (отвечает через done) · Библиотека: нет

Сигнатура
GetCharacterInfo(
  charId: number,
  done: (info: (CharacterInfo & { userId: number }) | null) => void,
): void
Lua
exports['ai-core']:GetCharacterInfo(charId, function(info) end) -- info: table или nil

Параметры

Prop

Type

Возвращает

Ничего. done получает CharacterInfo с ещё одним полем, userId (id аккаунта), или null для неизвестного или удалённого персонажа, неверного id или неудачного чтения. Если done не функция, вызов ничего не делает.

Пример

import { addCommand, resourceExport } from "@aicore-fivem/lib/server";

const core = resourceExport("ai-core");

addCommand("charinfo", {
  help: "Shows a character by id",
  params: [{ name: "charId", type: "number" }],
  restricted: true,
}, (_source, args) => {
  core.GetCharacterInfo(args.charId, (info) => {
    if (!info) return console.log("no such character");
    console.log(`${info.firstname} ${info.lastname} (${info.citizenid}), account ${info.userId}`);
  });
});

Сохранённый персонаж держится 5 минут после чтения, поэтому имя, изменённое в админ-панели, может столько же показывать старое значение. Загруженный персонаж всегда отвечает из памяти.

SwitchCharacter

Отправляет игрока обратно на экран персонажей, не выходя с сервера, как выход из персонажа. ai-core сначала сохраняет и выгружает персонажа, затем открывает экран.

Сторона: сервер · Ожидание: нет (выгрузка выполняется после возврата из вызова) · Библиотека: нет

Сигнатура
SwitchCharacter(src: number): boolean
Lua
local started = exports['ai-core']:SwitchCharacter(source) -- boolean

Параметры

Prop

Type

Возвращает

boolean: true, когда смена началась. false, когда у игрока нет загруженного персонажа.

Пример

import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";

const core = resourceExport("ai-core");

// Кнопка «Сменить персонажа» в вашем меню.
onClientCallback("myscript:logout", (source) =>
  core.SwitchCharacter(source) ? { ok: true } : fail("NO_CHARACTER"),
);

Ваш ресурс получает ai-core:playerUnloaded с причиной "switch", когда персонажа уже нет. Очищайте состояние, привязанное к персонажу, там, а не сразу после этого вызова.

SetOfflinePosition

Перемещает точку появления незагруженного персонажа: в следующий раз, когда этого персонажа выберут, он появится там. Используйте, когда что-то перемещает спящее тело или офлайн-персонажа (тело унесли, игрока отбуксировали).

Сторона: сервер · Ожидание: нет (запись идёт в фоне) · Библиотека: characters.setOfflinePosition

Сигнатура
SetOfflinePosition(
  charId: number,
  position: { x: number; y: number; z: number; heading?: number },
): boolean
Lua
local accepted = exports['ai-core']:SetOfflinePosition(charId, { x = x, y = y, z = z, heading = h })

Параметры

Prop

Type

Возвращает

boolean: true, когда перемещение принято; запись в базу данных выполняется, как только не идёт ни загрузка, ни сохранение этого персонажа (ждёт до 30 секунд). false, когда персонаж сейчас загружен, charId не целое число или координата отсутствует или не является конечным числом. Отсутствующий heading сохраняется как 0.

Пример

import { resourceExport } from "@aicore-fivem/lib/server";

const core = resourceExport("ai-core");
const HOSPITAL = { x: 298.6, y: -584.5, z: 43.3, heading: 70 };

/** A body left in the world too long is moved to the hospital. */
export function sendBodyToHospital(charId: number): void {
  if (!core.SetOfflinePosition(charId, HOSPITAL))
    console.log(`character ${charId} is online, not moved`);
}

Если персонаж загружается, пока запись ждёт, запись пропускается: пед загруженного персонажа находится там, где он на самом деле.

GetPlayersInScope

Игроки в зоне OneSync другого игрока: все, чья игра сейчас стримит этого игрока, примерно в 424 метрах вокруг. ai-core ведёт этот список по событиям зоны FiveM один раз для всех ресурсов, поэтому другим ресурсам никогда не нужно слушать эти события самим.

Сторона: сервер · Ожидание: нет · Библиотека: playersNear(source, radius) и playersNearEntity(entity, radius) строятся на нём и фильтруют по расстоянию

Сигнатура
GetPlayersInScope(source: number): number[]
Lua
local nearby = exports['ai-core']:GetPlayersInScope(source) -- список серверных id

Параметры

Prop

Type

Возвращает

number[]: серверные id других игроков в зоне (самого игрока в списке нет). Пустой список для игрока в одиночестве, неизвестного id или значения, которое не является числом.

Пример

import { coordsOf, resourceExport } from "@aicore-fivem/lib/server";
import { distance } from "@aicore-fivem/lib/shared";

const core = resourceExport("ai-core");

/** Plays a sound for everyone within 30 m of a player. */
export function playNear(source: number, sound: string): void {
  const at = coordsOf(source);
  for (const other of [source, ...core.GetPlayersInScope(source)])
    if (distance(coordsOf(other), at) <= 30) emitNet("myscript:sound", other, sound);
}

На этой странице