Перейти к содержимому

Ваш первый ресурс BS19

В этом руководстве мы с нуля соберём небольшой ресурс: команду /checkin, которая выдаёт выжившему бутылку воды, не чаще раза в час. Это займёт около 15 минут. Нужны запущенный сервер BS19, доступ к его файлам и консоли txAdmin и текстовый редактор (VS Code подойдёт).

Когда всё заработает, Свой ресурс поверх bs_core покажет следующие шаги: клиентский код, колбэки и ловушки, которых стоит избегать.

В папке resources сервера создайте папку [local] (квадратные скобки важны: так это категория, а не ресурс), а в ней папку bs_checkin. Держите свои ресурсы в [local], тогда обновления фреймворка их не перезапишут.

resources/[local]/bs_checkin/
├── fxmanifest.lua
├── config.lua
└── server.lua

Имя папки и есть имя ресурса. Начните его с bs_, чтобы не было конфликтов с другими скриптами.

Этот файл нужен каждому ресурсу FiveM. Он говорит серверу, какие файлы загружать и на какой стороне.

fx_version 'cerulean'
game 'gta5'
lua54 'yes'
name 'bs_checkin'
description 'My first BS19 resource'
shared_scripts {
'@bs_core/shared/sh_bridge.lua', -- gives you BSB (commands, callbacks)
'config.lua',
}
server_scripts { 'server.lua' }
dependencies { 'bs_core', 'bs_inventory' }

Строка @bs_core/shared/sh_bridge.lua подключает мост BS19 к вашему ресурсу. Без неё BSB не существует, и серверный файл падает с ошибкой.

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

Checkin = {
item = 'water_bottle', -- any item name from bs_inventory's item list
amount = 1,
cooldown = 3600, -- seconds between two check-ins (1 hour)
}
local lastCheckin = {} -- [charId] = os.time() of the last check-in
local function notify(src, kind, message)
TriggerClientEvent('bs:ui:notify', src, { type = kind, message = message })
end
BSB.RegisterCommand('checkin', nil, 'Daily survivor check-in', {}, function(src)
if src == 0 then return print('Run /checkin in game, not in the console.') end
local p = exports.bs_core:GetPlayerSummary(src)
if not p then return notify(src, 'error', 'Pick a character first.') end
local now = os.time()
local last = lastCheckin[p.charId]
if last and now - last < Checkin.cooldown then
local minutes = math.ceil((Checkin.cooldown - (now - last)) / 60)
return notify(src, 'error', ('Come back in %d min.'):format(minutes))
end
local ok, reason = exports.bs_inventory:GiveItem(src, Checkin.item, Checkin.amount)
if not ok then return notify(src, 'error', 'No room: ' .. tostring(reason)) end
lastCheckin[p.charId] = now
notify(src, 'success', ('Welcome back, %s. Here is some water.'):format(p.firstName))
end)

Что делает код, построчно:

  • BSB.RegisterCommand создаёт команду чата. nil значит, что её может использовать любой; укажите там ACE вроде 'bs.admin', чтобы оставить её только для администрации.
  • GetPlayerSummary возвращает nil, пока игрок ещё на экране выбора персонажа, поэтому проверяйте это первым делом.
  • Задержка хранится по персонажу (charId), а не по игроку, так что у второго персонажа свой check-in. Она сбрасывается при перезапуске ресурса, для первого ресурса этого достаточно.
  • Предметы всегда выдаются через exports.bs_inventory:GiveItem. Если инвентарь полон, он возвращает false и причину. Никогда не пишите в базу данных сами.

Добавьте эту строку в конец server.cfg, после ресурсов BS19:

ensure bs_checkin

Затем в живой консоли txAdmin (перезапуск сервера не нужен):

refresh
ensure bs_checkin

refresh заставляет сервер увидеть новую папку. В консоли должно появиться Started resource bs_checkin. Когда позже измените файл, для перезагрузки хватит одной команды ensure bs_checkin.

  1. Зайдите на сервер и выберите персонажа.
  2. Нажмите T, введите /checkin и нажмите Enter. Появится зелёное уведомление, а в инвентаре (I) бутылка воды.
  3. Введите /checkin ещё раз. Появится красное сообщение “Come back in 60 min.”.
Что вы видитеПочемуЧто делать
Couldn't find resource bs_checkinСервер не увидел папку или имя не совпадаетВыполните refresh, проверьте, что папка называется именно bs_checkin
attempt to index a nil value (global 'BSB')Нет строки мостаПроверьте строку @bs_core/shared/sh_bridge.lua в fxmanifest.lua
No such export GetPlayerSummarybs_core ещё не запущенДержите ensure bs_checkin ниже ресурсов BS19 в server.cfg
/checkin ничего не делает, ошибок нетВы ещё на экране персонажей или команда так и не зарегистрироваласьВыберите персонажа и поищите красную строку [bs_checkin] в консоли
“No room: …”Инвентарь полон или слишком тяжёлыйВыбросьте что-нибудь и попробуйте снова

Любая красная ошибка в консоли также указывает файл и строку. Исправьте, снова выполните ensure bs_checkin и попробуйте ещё раз.

  • Поменяйте item на bandage в config.lua и выполните ensure bs_checkin. Код менять не нужно.
  • Выдайте ещё и наличные: exports.bs_core:AddMoney(src, 'cash', 25, 'checkin').
  • Выдайте опыт: exports.bs_core:AddXP(src, 10, 'checkin').
  • Посмотрите доступные вызовы в Обзор exports и events.