Skip to content

Работа с рецептами

Рецепты находятся по пути lua/recipies/.../{recipe_name}.lua

Tip

Есть особая "магическая" папка - disabled. Она может находится в любой другой папке, но все рецепты внутри неё не будут загружены.

По образу и подобию систем в Metrostroi, первой строчкой в файле рецепта необходимо определить рецепт: MEL.DefineRecipe("{recipe_name}", "<train_type>")

Возможные значения для train_type:

  • Имя энтити - gmod_subway_81-717_mvm
  • Имя типа - 717 (применится на все два энтити поезда 717 - СПБ и МСК)
  • На все зарегистрированные в Metrostroi типы поездов - all
  • Поиск по имени энтити - mvm выберет все энтити, где есть mvm в названии
  • Таблица с именами энтити - {"gmod_subway_81-720", "gmod_subway_81-722"} выберет две энтити

Списов возможных типов:

  • 717 - применяется только на две энтити - 717_mvm и 717_lvz. Промежутки и кастомные вагоны не учитываются
  • 717_714 - применяется только на четыре энтити - 717_mvm и 714_mvm, 717_lvz и 714_lvz. Кастомные вагоны не учитываются
  • 717_714_mvm - применяется только на два энтити - 717_mvm и 714_mvm. Кастомные вагоны не учитываются
  • 717_714_lvz - применяется только на два энтити - 717_lvz и 714_lvz. Кастомные вагоны не учитываются
  • 718_719 - применяется только на два энтити - 718 и 719. Кастомные вагоны не учитываются

Фукнции внутри рецепта

  • RECIPE:Init() - поможет для инициализации каких-либо значений, использующихся в рецепте. Вызывается один раз при загрузке (или релоуде) рецепта
  • RECIPE:BeforeInject(entclass) - выполняется перед всеми инжектами. Тут необходимо модицифировать глобальные переменные других рецептов. См Глобальные переменные.
  • RECIPE:InjectNeeded(entclass) - вызывается перед каждым InjectSpawner и Inject. Данная функция должна вернуть true или false в зависимости от того, нужно ли производить инжект в данный тип вагонов
  • RECIPE:Inject(ent, entclass) - вызывается на каждой энтити, соответствующей типу рецепта. Обычно, тут и происходит весь инжект
  • RECIPE:InjectSpawner(entclass) - вызывается на каждой энтити, предназначен для инжекта в спавнер. Тут необходимо вызывать методы для работы со спавнером. Автоматом управляет значением entclass - к примеру, для простого 717_mvm в InjectSpawner произойдет инжект в 717_mvm_custom
  • RECIPE:InjectSystem() - предназначен для инжектов в системы.

Механизм управления рецептами, отключение определенного рецепта

Каждый рецепт создает свой ConVar, с помощью которого можно отключить его.

Для этого следует задать значение 0 ConVar'у данного рецепта.

Все ConVar можно посмотреть написав в клиентскую консоль find metrostroi_ext_. После префикса сначала идет тип энтити для инжекта, а потом название рецепта.

Tip

В helptext ConVar (можно просмотреть, если не указывать значение, а просто написать имя ConVar) указано описание рецепта (Если оно задано автором).

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

Warning

Пожалуйста, выключайте сервер командой exit - только так значение ваших ConVar будет сохраняться между перезапусками.

Переменные внутри рецептов

  • RECIPE.Description - описание рецепта. Помогает другим разработчикам, игрокам и администраторам серверов понять, что делает ваш рецепт (отображается в ConVar)
  • self.Specific (задается в Init) - RecipeSpecific переменная.

Recipe Specific переменные

Для возможности кастомизации уже существующих рецептов, в Metrostroi Extensions заложена возможность создания глобальных переменных рецептов. Для этого необходимо в функции RECIPE:Init() добавить в таблицу self.Specific какие-либо значения. После этого эти значения будут доступны всем рецептам через MEL.RecipeSpecific.<название_значения>.

Как пример можно рассмотреть стандартный рецепт работы с лампами. Мы задаем в Init новую таблицу SalonLampList, а дальше в коде обращаемся к ней как к MEL.RecipeSpecific.SalonLampList

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

Для этого просто необходимо добавить новое описание ламп в таблицу SalonLampList в функции RECIPE:BeforeInject()

К примеру, в тот же стандартный рецепт работы с лампами можно добавить новый тип ламп вот таким простым рецептом:

Lua
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
MEL.DefineRecipe("salon_lamp_minsk1_1", "717_714_mvm")
RECIPE.Description = "This recipe adds salon lamps from minsk, type1_1. "
local MODELS_ROOT = "models/metrostroi_extensions/81-717/interior/lamps/"
function RECIPE:BeforeInject()
    table.insert(MEL.RecipeSpecific.SalonLampList, {
        name = "MinskType1_1",
        head = {
            model = MODELS_ROOT .. "lamps_minsk_type1_717.mdl",
            glow = {
                model = MODELS_ROOT .. "lamps_minsk_type1_glow_717.mdl",
                model_emergency = MODELS_ROOT .. "lamps_minsk_type1_glow_emer.mdl",
                count = 1,
            },
        },
        int = {
            model = MODELS_ROOT .. "lamps_minsk_type1_714.mdl",
            glow = {
                model = MODELS_ROOT .. "lamps_minsk_type1_glow_714.mdl",
                model_emergency = MODELS_ROOT .. "lamps_minsk_type1_glow_emer.mdl",
                count = 1,
            },
        },
    })
end

Tip

Для удобства сторонних разработчиков рекомендуется документировать внутри своего кода описание формата вашей RecipeSpecific таблицы

Scoped-рецепты (разделение на sh, cl, sv)

Tip

Данный функционал будет полезен авторам приватного контента. Серверная часть рецепта при использовании scoped-рецептов никогда не передаеться на клиент.

В Metrostroi Extensions существует механизм разделения каждого рецепта на отдельный scope - shared, server, client

Для этого вместо одного файла рецепта необходимо создать папку с именем рецепта (представим, что это {recipe_name}), внутри которой может находиться три файла:

  • sh_{recipe_name}.lua - данный код выполнится на клиенте и сервере
  • cl_{recipe_name}.lua - данный код выполнится на клиенте
  • sv_{recipe_name}.lua - данный код выполнится на сервере

В каждом из данных файлов необходимо вызвать MEL.DefineRecipe("{recipe_name}", "<train_type>"), с одинаковым именем ({recipe_name}).

Debug-режим

В Metrostroi Extensions Lib существует Debug режим - он позволяет вам перезагружать рецепты "на лету" командой metrostroi_ext_reload и получать дополнительную отладочную информацию

Его состояние управляется серверной ConVar metrostroi_ext_debug, которая по умолчанию равна 0. При установке её в 1 - включается Debug режим.

Для работы в "продакшене" рекомендуется выключать Debug режим.

Warning

Если включить debug-режим, то любой игрок сможет вызвать metrostroi_ext_reload и перезагрузить все рецепты у всех клиентов.

metrostroi_ext_reload - перезагрузить все рецепты

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

С помощью этой команды можно производить разработку не переспавнивая состав и не перезаходя в игру.

Tip

Для ускорения разработки можно добавить file-watcher в вашей IDE, который будет автоматически при изменении любого из рецептов отправлять RCON запрос с вызовом metrostroi_ext_reload.

Вместе с Metrostroi Extensions Lib распространяется маленький скрипт на Python - scripts/reload.py, который поможет вам это сделать. При запуске он отправляет RCON запрос с командой metrostroi_ext_reload.

Для его работы:

  • необходимо установить библиотеку rcon - pip install rcon
  • создать в папке с reload.py .env файл, в котором указать адрес, порт и пароль от RCON:
    Carbon
    1
    2
    3
    RCON_IP={ваш ip address сервера}
    RCON_PORT={порт RCON}
    RCON_PASSWORD={пароль RCON}