ai-vehicles для разработчиков
Серверные экспорты, state bags и события ai-vehicles и API qbx_vehicles, на который он отвечает.
У ai-vehicles только серверные экспорты. Все они синхронные (без Promise, без ожидания в Lua), кроме SpawnVehicle, который отвечает через колбэк. Типы находятся в @aicore-fivem/shared (vehicles.ts).
import { resourceExport } from "@aicore-fivem/lib/server";
const vehicles = resourceExport("ai-vehicles");local vehicles = exports['ai-vehicles']Чтобы выдать, забрать или проверить ключи, поставить транспорт в гараж или прочитать топливо, используйте слои lib (vehicleKeys, garages, fuel): они работают с любым скриптом ключей, гаражей или топлива, который запущен на сервере. Вызывайте ai-vehicles напрямую только для самого владения.
Типы
VehicleOwner
Кому принадлежит транспорт.
Prop
Type
OwnedVehicle
Что возвращают GetVehicle и GetVehicles.
Prop
Type
Серверные экспорты
CreateVehicle
Регистрирует новый личный транспорт и ставит его в гараж. Используйте, когда игрок получает транспорт (покупка, награда, подарок администратора). Машину не создаёт: выведите её через SpawnVehicle или позвольте игроку забрать её в гараже.
Сторона: сервер · Ожидание: нет
CreateVehicle(owner: VehicleOwner, model: string, garage: string | null, props?: VehicleProps): { id: number; plate: string } | nulllocal created = exports['ai-vehicles']:CreateVehicle(owner, model, garage, props) -- { id = number, plate = string } или nilПараметры
Prop
Type
Возвращает
{ id, plate } нового транспорта. null, если owner не является корректным владельцем или model не текст.
Пример
import { resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
const vehicles = resourceExport("ai-vehicles");
// Даёт игроку Sultan, поставленный в гараж Motel Parking.
export function giveSultan(source: number): string | null {
const character = core.GetCharacter(source);
if (!character) return null;
const created = vehicles.CreateVehicle(
{ type: "character", id: String(character.id) },
"sultan",
"pillbox",
);
return created?.plate ?? null;
}GetVehicle
Находит один личный транспорт по id или номеру.
Сторона: сервер · Ожидание: нет
GetVehicle(ref: number | string): OwnedVehicle | nulllocal vehicle = exports['ai-vehicles']:GetVehicle(ref) -- таблица или nilПараметры
Prop
Type
Возвращает
OwnedVehicle или null, если ни у одного транспорта в памяти нет такого id или номера (в том числе если он принадлежит персонажу офлайн).
Пример
const vehicle = vehicles.GetVehicle("AI00001A");
if (vehicle) console.log(vehicle.model, vehicle.state, vehicle.fuel);GetVehicles
Весь транспорт одного владельца.
Сторона: сервер · Ожидание: нет
GetVehicles(owner: VehicleOwner): OwnedVehicle[]local list = exports['ai-vehicles']:GetVehicles(owner) -- массивПараметры
Prop
Type
Возвращает
Массив OwnedVehicle. Пустой для некорректного владельца, владельца без транспорта или персонажа офлайн.
Пример
const fleet = vehicles.GetVehicles({ type: "job", id: "police" });
const parked = fleet.filter((v) => v.state === "garage").length;
console.log(`police: ${parked} of ${fleet.length} cars parked`);IsOwnedPlate
Принадлежит ли номер личному транспорту в памяти.
Сторона: сервер · Ожидание: нет
IsOwnedPlate(plate: string): booleanlocal owned = exports['ai-vehicles']:IsOwnedPlate(plate)Возвращает
true, если у личного транспорта есть этот номер. false для неизвестного номера, не текстового значения или транспорта персонажа офлайн.
GetVehicleIdByEntity
Id в ai-vehicles для созданного личного транспорта.
Сторона: сервер · Ожидание: нет
GetVehicleIdByEntity(entity: number): number | nulllocal id = exports['ai-vehicles']:GetVehicleIdByEntity(entity)Параметры
Prop
Type
Возвращает
Id транспорта или null, если сущность не является личным транспортом, созданным ai-vehicles.
GetEntity
Сущность созданного личного транспорта.
Сторона: сервер · Ожидание: нет
GetEntity(id: number): number | nulllocal entity = exports['ai-vehicles']:GetEntity(id)Возвращает
Хэндл серверной сущности или null, если транспорт не снаружи или его сущность больше не существует.
GetPlateOwners
Весь личный транспорт в памяти в виде [plate, ownerType, ownerId]. Скрипт, которому нужно проверять много номеров (система ключей), читает это один раз при старте, а затем следит за событием ai-vehicles:owners, вместо того чтобы вызывать экспорт при каждой проверке.
Сторона: сервер · Ожидание: нет
GetPlateOwners(): Array<[plate: string, type: VehicleOwnerType, id: string]>local owners = exports['ai-vehicles']:GetPlateOwners() -- { { plate, type, id }, ... }Возвращает
Массив троек. Пустой, если в памяти нет транспорта.
SaveVehicle
Сохраняет состояние и вид транспорта: топливо, повреждения, состояние, гараж и props (цвета, дополнительные детали, грязь). Сохранённый тюнинг (mods, neon) здесь никогда не меняется, поэтому вид, прочитанный с клиента игрока, не может сохранить работу мод-меню. Для тюнинга используйте SaveTuning.
Сторона: сервер · Ожидание: нет
SaveVehicle(id: number, change: { props?: VehicleProps; fuel?: number; engine?: number; body?: number; state?: VehicleState; garage?: string | null }): voidexports['ai-vehicles']:SaveVehicle(id, change)Параметры
Prop
Type
change
Prop
Type
Возвращает
Ничего. Неизвестный id ничего не делает.
Пример
// Ремонт закончен: полный двигатель и кузов.
vehicles.SaveVehicle(vehicleId, { engine: 1000, body: 1000 });SaveTuning
Сохраняет полные props, включая тюнинг (mods, neon). Предназначен только для тюнинг-мастерских: собственная тюнинг-мастерская AI Core, ai-mechanic, является единственным скриптом ai-*, который его вызывает.
Сторона: сервер · Ожидание: нет
SaveTuning(id: number, props: VehicleProps): voidexports['ai-vehicles']:SaveTuning(id, props)Возвращает
Ничего. Некорректные props игнорируются. Номер внутри props всегда заменяется собственным номером транспорта.
Никогда не передавайте props, пришедшие прямо с клиента игрока, не проверив их на сервере: всё, что вы здесь сохраните, с этого момента становится тюнингом машины.
StoreVehicle
Ставит транспорт в гараж: удаляет его сущность, если он снаружи, и выставляет его состояние и гараж.
Сторона: сервер · Ожидание: нет
StoreVehicle(id: number, garage: string | null, state?: VehicleState): voidexports['ai-vehicles']:StoreVehicle(id, garage, state)Параметры
Prop
Type
Возвращает
Ничего. Сначала состояние не сохраняется: вызовите перед ним SaveVehicle, если нужно сохранить повреждения и топливо. Чтобы ставить в гараж через любой запущенный скрипт гаражей, используйте вместо этого garages.store из lib.
SetOwner
Передаёт транспорт другому владельцу (продажа между игроками, машина, перемещённая в автопарк работы).
Сторона: сервер · Ожидание: нет
SetOwner(id: number, owner: VehicleOwner): voidexports['ai-vehicles']:SetOwner(id, owner)Возвращает
Ничего. Некорректный владелец или неизвестный id ничего не делает. Ключи старого владельца не забираются: при необходимости уберите их через vehicleKeys.remove из lib.
Пример
vehicles.SetOwner(vehicleId, { type: "job", id: "mechanic" });DeleteVehicle
Удаляет личный транспорт навсегда: его сущность, если он снаружи, и его строку в базе данных.
Сторона: сервер · Ожидание: нет
DeleteVehicle(id: number): voidexports['ai-vehicles']:DeleteVehicle(id)Возвращает
Ничего.
Это нельзя отменить. Транспорт, его вид и тюнинг исчезают.
SpawnVehicle
Создаёт сущность личного транспорта в мире с его видом, номером, топливом и state bags и выдаёт ключи asker через активную систему ключей. Состояние транспорта становится out.
Сторона: сервер · Ожидание: нет (результат приходит в cb)
SpawnVehicle(id: number, at: { x: number; y: number; z: number; heading: number }, asker: number, cb: (netId: number | null) => void, purpose?: KeyPurpose, setup?: VehicleSetup): voidexports['ai-vehicles']:SpawnVehicle(id, at, asker, function(netId) end, purpose, setup)Параметры
Prop
Type
Возвращает
Ничего. cb получает network id или null, если транспорт не существует, уже снаружи, прямо сейчас создаётся или игра не смогла его создать.
Пример
import { resourceExport } from "@aicore-fivem/lib/server";
const vehicles = resourceExport("ai-vehicles");
export function bringOut(source: number, vehicleId: number): void {
const ped = GetPlayerPed(String(source));
const [x, y, z] = GetEntityCoords(ped);
const heading = GetEntityHeading(ped);
vehicles.SpawnVehicle(vehicleId, { x: x + 3, y, z, heading }, source, (netId) => {
if (netId === null) console.log(`vehicle ${vehicleId} could not come out`);
});
}Транспорт, который уже снаружи, отклоняется (cb(null)). Если его сущность позже исчезнет, пока он снаружи, он переходит в состояние штрафстоянки.
События
ai-vehicles:owners
Срабатывает, когда транспорт попадает в память ai-vehicles или меняет владельца, и когда номера уходят из памяти. Один пакет за серверный тик. Прочитайте GetPlateOwners один раз при старте, затем применяйте эти пакеты, чтобы держать копию «номер – владелец». Имя VEHICLES_EVENTS.owners в @aicore-fivem/shared.
Сторона: сервер (локальное событие, не отправляется клиентам)
Prop
Type
import { resourceExport } from "@aicore-fivem/lib/server";
import { VEHICLES_EVENTS } from "@aicore-fivem/shared";
const owners = new Map<string, string>();
for (const [plate, type, id] of resourceExport("ai-vehicles").GetPlateOwners())
owners.set(plate, `${type}:${id}`);
on(VEHICLES_EVENTS.owners, (puts: [string, string, string][], removes: string[]) => {
for (const [plate, type, id] of puts) owners.set(plate, `${type}:${id}`);
for (const plate of removes) owners.delete(plate);
});State bags
ai-vehicles выставляет их на каждом личном транспорте, который создаёт. Имена находятся в VEHICLE_BAGS (@aicore-fivem/shared).
| Bag | Тип | Значение |
|---|---|---|
ai:owned | true | Сущность является личным транспортом. |
ai:vid | number | Его id в ai-vehicles. |
ai:props | VehicleProps | Сохранённый вид. Его применяет клиент ai-core, которому принадлежит сущность. |
ai:setup | VehicleSetup | Вид при создании для транспорта без props, применяется один раз. |
fuel | number | Топливо 0-100. Дальше за ним следит скрипт топлива. |
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if Entity(vehicle).state['ai:owned'] then
print('owned vehicle', Entity(vehicle).state['ai:vid'])
endqbx_vehicles API
ai-vehicles делает provide для qbx_vehicles, поэтому эти вызовы доходят до него. Форматы следуют Qbox: state равно 0 снаружи, 1 гараж, 2 штрафстоянка.
| Экспорт | Что делает |
|---|---|
GetPlayerVehicles(filters: { citizenid?, garage? }) | Транспорт персонажа онлайн, по желанию только одного гаража. Возвращает { id, citizenid, modelName, garage, state, depotPrice, props }[]. |
GetPlayerVehicle(id: number) | Один транспорт в том же формате или nil. |
CreatePlayerVehicle(request: { model, citizenid, garage?, props? }) | Создаёт транспорт для персонажа онлайн. Возвращает id или nil, { code, message } (bad_request, not_found). |
SetPlayerVehicleOwner(id: number, citizenid: string) | Новый владелец (онлайн). true, если получилось. |
DeletePlayerVehicles(idType: "plate" | "vehicleId", idValue) | Удаляет один транспорт. true, если найден. |
GetVehicleIdByPlate(plate: string) | Id или nil. |
DoesPlayerVehiclePlateExist(plate: string) | true, если номер принадлежит личному транспорту. |
SaveVehicle(entity: number, options: { props?, state?, garage? }) | Сохраняет созданный транспорт, включая тюнинг. Принимает props AI Core или формат props ox_lib / qb-core. Props другой модели, чем у сущности, отклоняются (состояние и гараж всё равно сохраняются). |
GetPlayerVehicle возвращает props в формате VehicleProps AI Core, а не ox_lib. depotPrice всегда 0.