Продавців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-команди.