Продавцов28
Онлайн2

Автоматическая запись GOTV-демок для CS2 на Metamod:Source (фреймворк Pisex).
Аналог K4-GOTV-SwiftlyS2, но без SwiftlyS2 — чистый Metamod-плагин.
split_per_round) — отдельный файл на раунд.{map} {date} {time} {datetime} {round} {players} {server}.min_duration секунд удаляются автоматически.cleanup_hours — при старте карты и по таймеру.idle_stop_seconds..dem вложением,curl/rclone/gzip/…) — так закрываются!demo помечает текущую запись как нужнуюonly_requested 1 всё остальное удаляется).cs2-utils (IUtilsApi) и cs2-players (IPlayersApi) — обязательноtv_enable 1addons/gotv_demos/gotv_demos.so
addons/metamod/gotv_demos.vdf
addons/configs/gotv_demos.ini
Всё остальное — в addons/configs/gotv_demos.ini, файл подробно закомментирован.
После первого запуска посмотри в консоль сервера:
[GOTV] demo directory: /home/cs2/game/csgo/demos/
[GOTV] startup: server="..." addr="..." tv_enable=1 webhook=set http=pending
Если путь определился неверно — пропиши абсолютный путь к csgo/ в game_path.
В консоли выделенного сервера (pterodactyl, screen, stdin) работают только
настоящие ConCommand'ы с префиксом mm_:
| Команда | Что делает |
|---|---|
mm_gotv_status | Полное состояние: пути, cvar'ы, идёт ли запись |
mm_gotv_record | Начать запись |
mm_gotv_stop | Остановить и сохранить |
mm_gotv_cleanup | Прогнать чистку старых файлов |
mm_gotv_dir | Показать содержимое папки демок и очередь ожидания |
В чате и клиентской консоли — через cs2-utils:
| Клиентская консоль | Чат | Что делает |
|---|---|---|
gotv_status | !gotvstatus | То же состояние, вывод в консоль игрока |
gotv_record | !gotvrecord | Начать запись |
gotv_stop | !gotvstop | Остановить и сохранить |
gotv_demo | !demo, /demo | Игрок просит сохранить текущую демку |
Права — gotv_demos/admin (настраивается в admin_permission); !demo доступна всем.
Обычный вебхук принимает вложения до 10 МБ — отсюда max_upload_mb по умолчанию 9.
Файл больше лимита просто не прикладывается, эмбед с метаданными всё равно уходит.
Полный матч в один файл почти всегда больше 10 МБ, поэтому для вложений имеет смысл
либо split_per_round 1, либо связка upload_command + upload_url_format.
.demtv_record demos/foo создаёт файл demos/foo — без расширения, и такую
демку клиент не откроет. Плагин ищет обе формы имени, а закончив запись,
дописывает .dem сам — до заливки, так что на FTP и в Discord уходит уже
правильное имя. Отключается через force_dem_extension 0.
Пока файл ещё без расширения, чистка опознаёт демку по отсутствию точки в имени
— поэтому demo_directory должен быть отдельной папкой, а не самим csgo/
(если указать csgo/, чистка откажется работать вместо того, чтобы сносить
лишнее).
Из имени вырезается всё, кроме A-Za-z0-9._-; пробелы становятся _, подряд
идущие _ схлопываются, по краям обрезаются. Поэтому украшения в хостнейме
(▌ CS2.RU▌ PUBLIC #1) дают CS2.RU_PUBLIC_1, а не
<u>CS2.RU</u>PUBLIC_1__. Если хостнейм целиком нелатиницей, {server} не
даст ничего — задай латинское имя в server_name.
Очередь ожидающих демок живёт в памяти, поэтому kill -9 её теряет. Чтобы
демки при этом не оставались навсегда лежать на диске, при старте и на каждой
смене карты плагин сканирует папку: всё, что он не отслеживает сам и что не
менялось последнюю минуту, считается готовой демкой — заливается и уходит в
Discord. Отключается через orphan_scan 0.
Для таких «подобранных» демок неизвестны длительность, карта и раунды, поэтому
min_duration и only_requested к ним не применяются, а в эмбеде остаются
только имя, размер и время.
Если GOTV на сервере не поднялся, tv_record всё равно создаёт файл: движок
пишет заголовок, таблицы строк и Stop, но ни одного кадра игры. Такой файл
весит примерно 120 КБ независимо от длительности записи и содержит ровно 18
пакетов, из которых Packet — ноль.
Признак того, что дело именно в этом: файл закрыт штатно (есть Stop и
FileInfo), в userinfo видны живые игроки, а playback_time равен нулю.
Одна и та же длительность записи на другом сервере даёт мегабайты.
Первое, что надо проверить — GSLT (Steam Game Server Login Token). Если токен
не указан (в pterodactyl это переменная STEAM_ACC) или протух, сервер не
логинится в Steam, GOTV-инстанс не создаётся, и tv_record пишет ровно такую
пустышку. При этом tv_enable показывает 1, в консоли ошибок может не быть,
а сервер играется как обычно — поэтому причина и ищется долго. Именно этим
оказались вызваны пустые демки на 4 серверах из 10; после добавления токена всё
заработало сразу.
Причина №2 — bot_quota_mode fill выкидывает GOTV-бота. В конце разминки
игра подгоняет число клиентов под bot_quota, а SourceTV для движка — такой же
BOT. В консоли сервера:
Warmup period ended
SourceTV kicked by Console (NETWORK_DISCONNECT_KICKED)
Syfers kicked by Console (NETWORK_DISCONNECT_KICKED)
Сам GOTV-сервер при этом не выключается — порт слушается, status печатает
sourcetv[0], tv_enable равен 1. Мёртв только клиент. Проверяется через
tv_status: frames N / ticks N перестаёт расти и застывает на моменте кика,
хотя Online идёт дальше. После этого tv_record молча не делает ничего, а в
лог сервера падает GOTV[0] not active. — в консоль команда не пишет ни ошибки,
ни подтверждения. Лечится настройкой ботов на сервере, не плагином.
Дальше по списку — tv_enable, tv_maxclients, свободен ли слот под GOTV-бота,
не выставлен ли tv_enable уже после загрузки карты. Плагин печатает эти
переменные в лог при каждом старте записи и по команде mm_gotv_find — логи
рабочего и нерабочего сервера можно сравнить напрямую.
Проверка вручную на проблемном сервере: tv_record test, подождать полминуты,
tv_stoprecord. Если файл всё равно ~120 КБ — плагин ни при чём.
min_size_kb 200 не лечит причину, но не даёт пустышкам уезжать в Discord и
в хранилище.
Демка закрывается по любому из:
split_per_round 1;max_duration секунд с начала записи (0 = выключено);cs_win_panel_match);idle_stop_seconds.Отдельно стоит случай сервера с одной картой, которая не меняется. Если там
ещё и матч не заканчивается (бесконечный режим), то при split_per_round 0
демку закроет только опустевший сервер — файл будет расти часами и почти
наверняка перестанет влезать в лимит вложения Discord. Для такого сервера ставь
max_duration 1800 (или 3600), либо оставляй split_per_round 1.
Резать по размеру нельзя: пока запись идёт, файла на диске ещё нет — CS2
сбрасывает его только по окончании записи, поэтому размер измерить не из чего.
Ограничение работает по времени.
Движок закрывает .dem асинхронно — иногда через секунды после tv_stoprecord,
иногда только при смене карты. Поэтому плагин не гадает с задержкой: раз в секунду
он проверяет путь и считает демку готовой, когда файл появился и его размер не
менялся finalize_stable секунд. Ожидающие записи переживают смену карты.
Кроме того, после каждой остановки действует finalize_grace секунд тишины, в
течение которых новая запись не стартует: если дать tv_record сразу, движок не
успевает закрыть предыдущий файл и тот теряется совсем.
Если файл так и не появился за finalize_timeout, в лог выгружается листинг папки
демок — сразу видно, назвал ли движок файл иначе или его действительно нет.
То же самое по команде mm_gotv_dir.
debug 1 в конфиге → addons/logs/gotv_demos.txt: старт/стоп записи, причины
отбрасывания файлов, коды ответов Discord, pid и результат upload-команды.