Транспорт
spawnVehicle, vehicleType, randomPlate, ближайший транспорт, сущности по сетевым id от клиента, vehicleKeys, топливо и гаражи.
import { spawnVehicle, vehicleKeys, fuel, garages, vehicleFromNet } from "@aicore-fivem/lib/server";Спавн
spawnVehicle
Создаёт сетевой транспорт на сервере и настраивает его одним вызовом: номер, топливо, внешний вид, замок, routing bucket, ключи для нужной цели, водитель и пассажиры. Используйте для каждого транспорта скрипта (рабочий транспорт, аренда, транспорт из гаража, спавн администратором).
Сторона: Сервер · Ждёт: да (Promise в TypeScript, в Lua приостанавливает поток)
spawnVehicle(options: SpawnVehicleOptions): Promise<number | null>local vehicle = aiLib.spawnVehicle(options) -- сущность или nil, вызывайте внутри потокаПараметры
Prop
Type
SpawnVehicleOptions
Prop
Type
Возвращает
Promise<number | null>: хэндл сущности транспорта. null, если модель не существует (так сказал клиент asker), сущность не создалась за 5 секунд или тип неизвестен.
Пример
import { onClientCallback, spawnVehicle, hasCharacter, near } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
const DEPOT = { x: 895.4, y: -179.3, z: 74.7 };
onClientCallback(
"my-taxi:start",
async (source) => {
const vehicle = await spawnVehicle({
model: "taxi",
coords: { x: 899.1, y: -180.6, z: 73.8, heading: 238 },
asker: source,
keysTo: source,
purpose: "job",
driver: source,
fuel: 100,
setup: { dirt: 0 },
});
if (!vehicle) return fail("SPAWN_FAILED");
return { ok: true, netId: NetworkGetNetworkIdFromEntity(vehicle) };
},
{ guards: [hasCharacter(), near(DEPOT, 5)], lock: true },
);Ключи ждут (до 3 секунд), пока сервер не прочитает номер: до первой синхронизации клиента-владельца сервер читает пустой номер. Посаженных игроков сажают снова в течение до 2 секунд, пока они не сядут. В TypeScript тип модели от одного клиента служит только этому игроку, пока клиент второго игрока не даст тот же ответ; Lua-аналог сохраняет первый полученный ответ.
vehicleType
Тип спавна модели, запрошенный у клиента игрока. Используйте, чтобы проверить, что модель существует, прежде чем брать деньги.
Сторона: Сервер · Ждёт: да (Promise)
vehicleType(model: string, asker: number): Promise<string | null>Lua-аналога нет: aiLib.spawnVehicle с asker проверяет это и возвращает nil для неизвестной модели.
Prop
Type
Возвращает
Promise<string | null>: automobile, bike, boat, heli, plane, submarine, trailer или train; null, если в игре нет такого транспорта или клиент не дал верного ответа. Ответ сохраняется для всех, как только клиенты двух разных игроков совпали в нём, поэтому один модифицированный клиент может сломать только собственные спавны.
Пример
import { onClientCallback, vehicleType } from "@aicore-fivem/lib/server";
import { fail, oneArg, readText } from "@aicore-fivem/lib/shared";
onClientCallback("my-dealer:buy", { args: oneArg((v) => readText(v, 32)), lock: true }, async (source, model) => {
if (!(await vehicleType(model, source))) return fail("UNKNOWN_MODEL");
// забираем деньги, затем spawnVehicle(...)
return { ok: true };
});randomPlate
Случайный номер, похожий на игровой (две цифры, три буквы, три цифры), или ваш префикс с цифрами после него.
Сторона: Сервер · Ждёт: нет
randomPlate(prefix?: string): stringLua-аналога нет (aiLib.spawnVehicle задаёт случайный номер, если вы его не передали).
Prop
Type
Возвращает номер из 8 символов (42ABC123 или TAXI1234 для randomPlate("TAXI")). Уникальность не проверяется: проверьте свою таблицу перед сохранением.
const plate = randomPlate("RENT");Поиск транспорта
nearestVehicleTo
Ближайший транспорт в пределах metres от игрока, который проходит ваш фильтр. Транспорт, в котором сидит игрок, побеждает первым.
Сторона: Сервер · Ждёт: нет
nearestVehicleTo(source: number, metres: number, filter?: (vehicle: number) => boolean): numberlocal vehicle = aiLib.nearestVehicleTo(source, metres, filter) -- сущность или 0Prop
Type
Возвращает сущность транспорта или 0, если ничего нет.
const vehicle = nearestVehicleTo(source, 5);
if (!vehicle) return fail("NO_VEHICLE");Перебирает весь транспорт на сервере: используйте для команд и действий (с ограничением частоты), никогда в тике.
nearestVehicleAt
Ближайший транспорт в пределах metres от точки. Используйте, чтобы проверить, что место спавна свободно.
Сторона: Сервер · Ждёт: нет
nearestVehicleAt(point: { x: number; y: number; z: number }, metres: number, filter?: (vehicle: number) => boolean): numberLua-аналога нет.
Возвращает сущность транспорта или 0, если ничего нет. Перебирает весь транспорт, как nearestVehicleTo.
const SPOT = { x: 899.1, y: -180.6, z: 73.8 };
if (nearestVehicleAt(SPOT, 3)) return fail("SPOT_BLOCKED");Сущности из ввода клиента
Клиент отправляет сетевой id, а не хэндл сущности. Эти функции превращают сетевой id в живую серверную сущность и проверяют её, поэтому вам никогда не нужно вручную вызывать NetworkGetEntityFromNetworkId + DoesEntityExist + GetEntityType.
entityFromNet
Живая сущность за сетевым id от клиента.
Сторона: Сервер · Ждёт: нет
entityFromNet(netId: unknown, type?: 1 | 2 | 3): numberLua-аналога нет (в Lua есть vehicleFromNet).
Prop
Type
Возвращает сущность или 0, если значение не является положительным целым числом, не сетевое, исчезло или другого типа.
const prop = entityFromNet(rawNetId, 3);
if (!prop) return fail("NOT_FOUND");pedFromNet
entityFromNet(netId, 1): живой пед или 0.
Сторона: Сервер · Ждёт: нет
pedFromNet(netId: unknown): numberLua-аналога нет.
const ped = pedFromNet(rawNetId);vehicleFromNet
entityFromNet(netId, 2): живой транспорт или 0.
Сторона: Сервер · Ждёт: нет
vehicleFromNet(netId: unknown): numberlocal vehicle = aiLib.vehicleFromNet(netId) -- сущность или 0const vehicle = vehicleFromNet(rawNetId);
if (!vehicle) return fail("NO_VEHICLE");vehicleNearPlayer
Транспорт за сетевым id от клиента, но только если игрок рядом с ним (или на месте водителя).
Сторона: Сервер · Ждёт: нет
vehicleNearPlayer(source: number, netId: unknown, options?: { metres?: number; driver?: boolean }): numberlocal vehicle = aiLib.vehicleNearPlayer(source, netId, options) -- сущность или 0Prop
Type
Возвращает транспорт или 0, если id неверный, транспорт исчез или игрок слишком далеко / не водитель.
onClientCallback("my-tow:hook", { args: oneArg(readId), lock: true }, (source, netId) => {
const vehicle = vehicleNearPlayer(source, netId, { metres: 6 });
if (!vehicle) return fail("TOO_FAR");
return { ok: true };
});Ключи
vehicleKeys работает через слой ключей ai-core: отвечает скрипт ключей, запущенный на сервере (ai-vehiclekeys или другой, выбранный владельцем). Транспорт задаётся хэндлом серверной сущности или номером.
vehicleKeys.give
Выдаёт игроку ключи от транспорта.
Сторона: Сервер · Ждёт: нет
vehicleKeys.give(source: number, vehicle: number | string, purpose?: KeyPurpose): voidaiLib.vehicleKeys.give(source, vehicle, purpose)Prop
Type
Возвращает void.
vehicleKeys.give(source, vehicle, "rental");vehicleKeys.remove
Забирает у игрока ключи от транспорта.
Сторона: Сервер · Ждёт: нет
vehicleKeys.remove(source: number, vehicle: number | string): voidaiLib.vehicleKeys.remove(source, vehicle)Возвращает void.
vehicleKeys.remove(source, "RENT1234");vehicleKeys.has
Есть ли у игрока ключи.
Сторона: Сервер · Ждёт: нет
vehicleKeys.has(source: number, vehicle: number | string): booleanlocal has = aiLib.vehicleKeys.has(source, vehicle)Возвращает boolean. true также, если скрипт ключей не может сказать или никакой не запущен, поэтому не используйте это как единственную защиту чего-то ценного.
if (!vehicleKeys.has(source, vehicle)) return fail("NO_KEYS");Топливо
fuel читает и задаёт топливо транспорта (от 0 до 100) через слой топлива ai-core, какой бы скрипт топлива ни был запущен. На сервере Lua-аналога нет: вызывайте экспорты ai-core GetVehicleFuel / SetVehicleFuel.
fuel.get
Сторона: Сервер · Ждёт: нет
fuel.get(vehicle: number): number | nullВозвращает уровень топлива серверной сущности транспорта (от 0 до 100) или null, если его нет.
const level = fuel.get(vehicle) ?? 0;fuel.set
Сторона: Сервер · Ждёт: нет
fuel.set(vehicle: number, level: number): booleanProp
Type
Возвращает true, если задано, false для неверного транспорта.
fuel.set(vehicle, 100);fuel.provider
Сторона: Сервер · Ждёт: нет
fuel.provider(): string | nullВозвращает имя ресурса скрипта топлива, который отвечает (ai-fuel, ox_fuel, LegacyFuel...), или null, если никакой не запущен.
console.log(`fuel through ${fuel.provider() ?? "nothing"}`);Гаражи
garages работает через слой гаражей ai-core, какой бы скрипт гаражей ни был запущен; каждый скрипт отвечает только на то, что он предоставляет. Lua-аналога нет.
garages.impound
Отправляет транспорт на штрафстоянку или открывает форму штрафстоянки скрипта гаражей для by.
Сторона: Сервер · Ждёт: нет
garages.impound(vehicle: number, by?: number): booleanProp
Type
Возвращает true, если скрипт гаражей принял транспорт. false, если никто его не принял: удалите транспорт сами.
if (!garages.impound(vehicle, source)) DeleteEntity(vehicle);garages.store
Ставит транспорт в гараж.
Сторона: Сервер · Ждёт: нет
garages.store(vehicle: number, garage?: string | null, by?: number): booleanProp
Type
Возвращает true, если поставлен, false, если никто его не принял.
if (!garages.store(vehicle, "legion", source)) return fail("STORE_FAILED");garages.open
Открывает меню гаража скрипта гаражей для игрока.
Сторона: Сервер · Ждёт: нет
garages.open(source: number, garage?: string | null): booleanВозвращает true, если открыто, false, если в скрипте нет такого меню.
garages.open(source, "pillbox");garages.stored
Транспорт игрока в гаражах или на штрафстоянке.
Сторона: Сервер · Ждёт: да (Promise)
garages.stored(source: number): Promise<GaragedVehicle[] | null>Возвращает GaragedVehicle[] (plate, model, garage, impounded) или null, если скрипт не может сказать или ai-core остановлен.
const list = await garages.stored(source);
const impounded = list?.filter((v) => v.impounded).length ?? 0;garages.provider
Сторона: Сервер · Ждёт: нет
garages.provider(): string | nullВозвращает скрипт гаражей, который отвечает, или null, если никакой не запущен.
if (!garages.provider()) console.warn("no garage script runs");