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

Предметы

Добавлять, забирать, считать и проверять предметы в любом инвентаре, регистрировать тайники, магазины скриптов и используемые предметы, читать определения предметов и переносимый вес.

Каждый вызов предметов идёт через ai-core, а не через собственные экспорты скрипта инвентаря. ai-core передаёт каждый вызов активному инвентарю: тому, что выбран в настройке панели Inventory script, или первому запущенному, когда выбрано автоматически (ai-inventory, ox_inventory, qb-inventory, tgiann-inventory и остальные из списка совместимости). Когда владелец сервера меняет инвентарь, ваш скрипт продолжает работать без изменений.

Что нужно знать:

  • Инвентарь задаётся через InventoryRef: серверный id игрока (число) для карманов этого игрока или текстовый id для всего остального (имя тайника, номер багажника). См. InventoryRef.
  • Имена предметов - это имена предметов в инвентаре (water, bandage, WEAPON_PISTOL).
  • Метаданные - таблица дополнительных значений одной стопки (серийный номер, прочность). См. ItemMetadata.
  • Пока ни один инвентарь не работает, каждый вызов отвечает своим «пустым» значением: false, 0, пустой список или null.
  • Тайники, магазины и используемые предметы, которые вы регистрируете, хранит ai-core и передаёт каждому инвентарю, который становится активным позже, в том числе после перезапуска инвентаря. Регистрируйте их один раз при старте скрипта.

AddItem

Выдаёт предметы в инвентарь.

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

Сигнатура
AddItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): boolean
Lua
local ok = exports['ai-core']:AddItem(source, 'water', 2)

Параметры

Prop

Type

Возвращает

boolean: true, когда инвентарь добавил предметы. false, когда они не помещаются, предмета нет в инвентаре, аргумент неверен (count меньше 1, пустое имя предмета) или ни один инвентарь не работает.

Пример

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

const core = resourceExport("ai-core");
const TAP = { x: 1206.4, y: -3110.2, z: 5.6 };

onClientCallback("myscript:fillBottle", { guards: [near(TAP, 2)], lock: true }, (source) => {
  if (!core.RemoveItem(source, "empty_bottle")) return fail("NO_BOTTLE");
  if (!core.AddItem(source, "water")) {
    core.AddItem(source, "empty_bottle");
    return fail("NO_SPACE");
  }
  return { ok: true };
});

RemoveItem

Забирает предметы из инвентаря.

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

Сигнатура
RemoveItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): boolean
Lua
local ok = exports['ai-core']:RemoveItem(source, 'lockpick', 1)

Параметры

Prop

Type

Возвращает

boolean: true, когда предметы забраны. false, когда в инвентаре их меньше (тогда не забирается ничего), аргумент неверен или ни один инвентарь не работает.

Пример

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

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

onClientCallback("myscript:pickLock", { lock: true }, async (source) => {
  if (!core.HasItem(source, "lockpick")) return fail("NO_LOCKPICK");
  const result = await minigameFor(source, { game: "lockpick", minMs: 1500 });
  if (result === "broken") core.RemoveItem(source, "lockpick");
  return result === "won" ? { ok: true } : fail("LOCKPICK_FAILED");
});

GetItemCount

Сколько предмета лежит в инвентаре.

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

Сигнатура
GetItemCount(inv: InventoryRef, item: string, metadata?: ItemMetadata): number
Lua
local count = exports['ai-core']:GetItemCount(source, 'fish')

Параметры

Prop

Type

Возвращает

number: сумма по всем стопкам. 0, когда предмета нет, аргумент неверен или ни один инвентарь не работает.

Пример

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

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

// Скупщик рыбы показывает, сколько получит игрок.
onClientCallback("myscript:fishQuote", (source) => ({
  ok: true,
  price: core.GetItemCount(source, "fish") * 25,
}));

HasItem

Есть ли в инвентаре хотя бы заданное количество предмета.

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

Сигнатура
HasItem(inv: InventoryRef, item: string, count?: number): boolean
Lua
local has = exports['ai-core']:HasItem(source, 'repairkit')

Параметры

Prop

Type

Возвращает

boolean: true, когда в инвентаре count или больше. false, когда меньше, count меньше 1 или ни один инвентарь не работает.

Пример

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

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

onClientCallback("myscript:repair", { lock: true }, async (source) => {
  if (!core.HasItem(source, "repairkit")) return fail("NO_KIT");
  if (!(await progressFor(source, { label: Locale("REPAIRING"), duration: 8000 }))) return fail("CANCELLED");
  if (!core.RemoveItem(source, "repairkit")) return fail("NO_KIT");
  return { ok: true };
});

Проверяйте снова по ответу RemoveItem после всего, что ждёт (полоса прогресса, мини-игра): игрок мог тем временем выбросить предмет.

CanCarryItem

Поместятся ли предметы в инвентарь (вес и слоты), без их добавления.

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

Сигнатура
CanCarryItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata): boolean
Lua
local fits = exports['ai-core']:CanCarryItem(source, 'water', 5)

Параметры

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:buyWater", { lock: true }, (source) => {
  if (!core.CanCarryItem(source, "water", 5)) return fail("NO_SPACE");
  if (!core.RemoveMoney(source, "cash", 50, "shop_water")) return fail("NOT_ENOUGH_MONEY");
  core.AddItem(source, "water", 5);
  return { ok: true };
});

GetItems

Все стопки в инвентаре, с названиями.

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

Сигнатура
GetItems(inv: InventoryRef): InventoryStack[]
Lua
local stacks = exports['ai-core']:GetItems(source) -- список таблиц

Параметры

Prop

Type

Возвращает

InventoryStack[]: по записи на каждую стопку с name, label, count, slot и metadata. См. InventoryStack. Пустой список для пустого или неизвестного инвентаря, неверного аргумента или когда ни один инвентарь не работает.

Пример

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

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

// Ломбард перечисляет все предметы игрока, которые он покупает.
const BUYS: Record<string, number> = { gold_ring: 120, rolex: 400 };

onClientCallback("myscript:pawnList", (source) => ({
  ok: true,
  rows: core.GetItems(source)
    .filter((stack) => BUYS[stack.name] !== undefined)
    .map((stack) => ({ slot: stack.slot, label: stack.label, count: stack.count, price: BUYS[stack.name] })),
}));

ClearInventory

Полностью очищает инвентарь.

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

Сигнатура
ClearInventory(inv: InventoryRef): void
Lua
exports['ai-core']:ClearInventory(source)

Параметры

Prop

Type

Возвращает

Ничего. Неверный аргумент или отсутствие работающего инвентаря ничего не делают.

Пример

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

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

addCommand("clearinv", { help: "Empties a player inventory", params: [{ name: "id", type: "playerId" }], restricted: true }, (_source, args) => {
  core.ClearInventory(args.id);
});

Это нельзя отменить. Держите это за админской командой или понятным игровым правилом (приём в тюрьму, который сначала сохраняет предметы).

RegisterStash

Создаёт тайник: ящик для хранения, который игроки открывают по его имени. ai-core хранит его и снова регистрирует в каждом инвентаре, который становится активным.

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

Сигнатура
RegisterStash(name: string, label: string, slots: number, maxWeight: number, jobs?: string[]): void
Lua
exports['ai-core']:RegisterStash('police_evidence', 'Evidence', 100, 500000, { 'police' })

Параметры

Prop

Type

Значения по умолчанию применяются, когда значение отсутствует или неверно.

Возвращает

Ничего. Без текстового name вызов ничего не делает. Повторная регистрация того же имени заменяет тайник.

Пример

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

const core = resourceExport("ai-core");
const LOCKER = { x: 474.9, y: -994.7, z: 26.3 };

// Один раз при старте; ai-core передаёт его инвентарям, которые стартуют позже.
core.RegisterStash("police_evidence", Locale("STASH_EVIDENCE"), 100, 500_000, ["police"]);

onClientCallback("myscript:openEvidence", { guards: [near(LOCKER, 2)] }, (source) => {
  if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
  return core.OpenInventory(source, "police_evidence") ? { ok: true } : fail("STASH_FAILED");
});

OpenInventory

Открывает на экране игрока тайник, багажник или инвентарь другого игрока рядом с его собственным.

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

Сигнатура
OpenInventory(source: number, inv: InventoryRef): boolean
Lua
local opened = exports['ai-core']:OpenInventory(source, 'police_evidence')

Параметры

Prop

Type

Возвращает

boolean: true, когда инвентарь открыл экран. false, когда не смог (неизвестный тайник, у игрока нет инвентаря), аргумент неверен или ни один инвентарь не работает.

Пример

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

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

// Полиция обыскивает стоящего рядом игрока в наручниках.
onClientCallback("myscript:search", { args: oneArg(readId) }, (source, target) => {
  if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
  if (target === source || !isNear(target, coordsOf(source), 2)) return fail("TOO_FAR");
  return core.OpenInventory(source, target) ? { ok: true } : fail("SEARCH_FAILED");
});

Инвентарь здесь не проверяет ни расстояние, ни права. Проверьте работу, расстояние и состояние цели сами, прежде чем вызывать.

RegisterShop

Создаёт магазин скрипта: список предметов с ценами, который ваш скрипт открывает игроку (оружейная, торговый автомат). Инвентарь рисует магазин и принимает оплату по-своему (наличные, затем банк). ai-core хранит его и передаёт каждому инвентарю, который становится активным.

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

Сигнатура
RegisterShop(name: string, label: string, items: ShopProduct[]): void
Lua
exports['ai-core']:RegisterShop('police_armoury', 'Armoury', { { name = 'bandage', price = 0 } })

Параметры

Prop

Type

См. ShopProduct.

Возвращает

Ничего. Без текстового name или без единого допустимого товара вызов ничего не делает. Повторная регистрация того же имени заменяет магазин.

Пример

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

const core = resourceExport("ai-core");
const ARMOURY = { x: 482.6, y: -995.2, z: 30.7 };

core.RegisterShop("police_armoury", Locale("SHOP_ARMOURY"), [
  { name: "WEAPON_STUNGUN", price: 0 },
  { name: "bandage", price: 10 },
]);

onClientCallback("myscript:armoury", { guards: [near(ARMOURY, 2)] }, (source) => {
  if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
  return core.OpenShop(source, "police_armoury") ? { ok: true } : fail("SHOP_FAILED");
});

OpenShop

Открывает на экране игрока магазин, зарегистрированный через RegisterShop.

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

Сигнатура
OpenShop(source: number, name: string): boolean
Lua
local opened = exports['ai-core']:OpenShop(source, 'police_armoury')

Параметры

Prop

Type

Возвращает

boolean: true, когда магазин открылся. false, когда магазина с таким именем нет, у активного инвентаря нет магазинов скриптов, он не смог открыть или ни один инвентарь не работает.

Пример

См. пример RegisterShop выше: зарегистрируйте один раз при старте, затем открывайте после собственных проверок работы и расстояния.

Как и OpenInventory, это не проверяет ни расстояние, ни доступ. Проверьте их сначала.

RegisterUsableItem

Делает предмет используемым: когда игрок использует его в инвентаре, выполняется ваша функция. ai-core хранит функцию, поэтому она работает с инвентарями, которые стартуют позже, и переживает перезапуск инвентаря.

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

Сигнатура
RegisterUsableItem(name: string, handler: UsableItemHandler): void
// UsableItemHandler = (source: number, item: UsedItem) => unknown
Lua
exports['ai-core']:RegisterUsableItem('bandage', function(source, item) end)

Параметры

Prop

Type

См. UsableItemHandler и UsedItem.

Возвращает

Ничего. Без текстового name или функции вызов ничего не делает. Второй вызов для того же предмета заменяет обработчик.

Что происходит с предметом после использования, зависит от инвентаря: инвентари, которые сами забирают использованный предмет (ai-inventory забирает количество consume предмета), оставляют его, когда ваш обработчик возвращает false; другие инвентари следуют своим настройкам предметов, поэтому там при необходимости забирайте предмет сами.

Пример

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

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

core.RegisterUsableItem("bandage", (source) => {
  // Обработчик должен ответить сразу; часть со временем выполняется отдельно.
  void (async () => {
    if (!(await progressFor(source, { label: Locale("BANDAGING"), duration: 4000 }))) return;
    if (!core.RemoveItem(source, "bandage")) return;
    emitNet("myscript:client:heal", source, 25); // ваш клиентский скрипт добавляет здоровье
  })();
  return false; // оставить: он забирается выше, когда полоса закончилась
});

Использование также вызывает серверное событие ai-core:itemUsed (src, name, status), за которым следят эффекты предметов вроде голода и жажды. См. События и состояние.

GetItemDefinition

Один предмет так, как его определяет активный инвентарь: название, вес, складывается ли в стопку, картинка.

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

Сигнатура
GetItemDefinition(name: string): ItemDefinition | null
Lua
local def = exports['ai-core']:GetItemDefinition('water') -- table или nil

Параметры

Prop

Type

Возвращает

ItemDefinition | null: предмет с name, label, weight, unique, close, description и image, если у инвентаря она есть. См. ItemDefinition. null для неизвестного предмета, пустого имени или когда ни один инвентарь не работает.

Пример

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

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

/** "You received 2x Water" with the inventory's own label. */
export function giveWithNotice(source: number, item: string, count: number): void {
  if (!core.AddItem(source, item, count)) return;
  const label = core.GetItemDefinition(item)?.label ?? item;
  notify(source, Locale("NOTIFY_RECEIVED", count, label), "success");
}

GetItemDefinitions

Все предметы, которые определяет активный инвентарь, с ключами по имени. Используйте редко (чтобы один раз построить список); для одного предмета используйте GetItemDefinition.

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

Сигнатура
GetItemDefinitions(): Record<string, ItemDefinition>
Lua
local items = exports['ai-core']:GetItemDefinitions() -- таблица с ключами по имени предмета

Параметры

Нет.

Возвращает

Record<string, ItemDefinition>: все предметы. Пустая таблица, пока ни один инвентарь не работает.

Пример

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

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

/** Warns at start about items in your config that the inventory does not know. */
export function checkItems(names: string[]): void {
  const known = core.GetItemDefinitions();
  for (const name of names) if (!known[name]) console.log(`unknown item: ${name}`);
}

Выполняйте такую проверку после старта инвентаря: сразу после запуска сервера инвентарь может ещё не работать, и таблица будет пустой.

GetInventoryWeight

Что игрок несёт и может нести, по весу.

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

Сигнатура
GetInventoryWeight(source: number): { weight: number; maxWeight: number } | null
Lua
local w = exports['ai-core']:GetInventoryWeight(source) -- { weight, maxWeight } или nil

Параметры

Prop

Type

Возвращает

{ weight, maxWeight } | null: переносимый вес и лимит в граммах. null, когда активный инвентарь их не сообщает, у игрока не загружен инвентарь или ни один инвентарь не работает.

Пример

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

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

onClientCallback("myscript:weight", (source) => {
  const w = core.GetInventoryWeight(source);
  return { ok: true, free: w ? w.maxWeight - w.weight : null };
});

UseItem

Запускает обработчик, зарегистрированный для предмета, как будто игрок его использовал. Его вызывает мост ESX / QB в ai-core (из ESX.UseItem и CanUseItem в QB); у обычного скрипта нет причин это делать.

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

Сигнатура
UseItem(source: number, name: string, item?: unknown): unknown
Lua
local result = exports['ai-core']:UseItem(source, 'bandage', stack)

Параметры

Prop

Type

Возвращает

unknown: то, что вернул обработчик. false, когда обработчик не зарегистрирован, аргументы неверны или обработчик бросил ошибку (она записывается в лог).

Пример

Без примера: его вызывают инвентари и мост. Чтобы реагировать на использование, зарегистрируйте предмет через RegisterUsableItem.

IsUsableItem

Зарегистрирован ли обработчик для предмета. Его использует мост ai-core.

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

Сигнатура
IsUsableItem(name: string): boolean
Lua
local usable = exports['ai-core']:IsUsableItem('bandage')

Параметры

Prop

Type

Возвращает

boolean: true, когда какой-то ресурс зарегистрировал предмет через RegisterUsableItem. Иначе false.

Пример

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

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

/** Item tooltips show "Use" only for usable items. */
export function canUse(item: string): boolean {
  return core.IsUsableItem(item);
}

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