02 · Экосистема EloStore
CS2-серверы
Скинченджер, матч-движок и бродкаст
Свои игровые серверы на своем коде: скины из кабинета на сайте появляются в игре по SteamID, турниры грузятся из админки, трансляция получает живой killfeed. 3 своих плагина на C#, 1 755 строк без сторонних плагинов и 0 переключений оружия, чтобы скин встал.
Скины из кабинета
Игрок выбирает раскраску в кабинете на сайте, заходит на сервер, и она уже в руках. Здесь те же рендеры, что видит игрок в кабинете.
Рендеры из кабинета elostore.ru












Ножи и перчатки
Модель ножа и краска встают в момент выдачи, до первого кадра: без переключения оружия.





Свой движок раскрасок
Готового способа запечь раскраску CS2 на модель для сайта не было, поэтому около месяца мы собирали скинченджер и свой движок с нуля: модель и краска берутся из файлов игры, формулы краски повторяют шейдер CS2, а каждый результат сверяется с иконкой Valve.
Интерфейс воссоздан: модель и узор из файлов игры, шейдер из вьюера движка, числа в терминале условные
0
раскраски собрал движок
0
модели оружия из файлов игры
8
стилей краски по формулам шейдера

Задача
Турнирам и скинам EloStore нужен был свой сервер, а не чужие плагины с закрытым поведением.
Задача: связать сайт и игру. Игрок настраивает все на сайте, заходит на сервер, и все уже на месте: скины, состав, фазы матча, трансляция.
Срез по слоям
- Интерфейспиксель
- Кабинет скинов на сайте, турнирные сетки, админка матчей, оверлей для OBS
- Логикаденьги и правила
- Фазы матча, вето карт, сетки Single Elimination и Round Robin, режиссер событий трансляции
- Данныесхема и миграции
- Лоадауты по SteamID, каталог скинов, агентов и наклеек, статистика матчей в Postgres
- Сервервыкладка и эксплуатация
- Выделенный CS2-сервер под systemd от отдельного пользователя, RCON закрыт снаружи
- Безопасностьядро
- Токен в GSI-конфиге против поддельного стейта, whitelist ростера, API для сервера за токеном
Скинченджер EloSkins

Игрок выбирает скины оружия, ножи, перчатки, агентов и наклейки в кабинете на сайте, и они появляются в игре.
- 01При авторизации игрока плагин забирает лоадаут по SteamID из API сайта, скины настраиваются отдельно для T и CT
- 02Краска ложится в момент создания сущности (OnEntitySpawned) и в хуке GiveNamedItem, до первого рендера: модель ножа и краска встают без переключений
- 03Краска кладется нативом CAttributeList_SetOrAddAttributeValueByName по сигнатуре из gamedata
- 04Модели агентов прекешируются на старте карты, иначе SetModel небезопасен
- 05Команда !ws обновляет скины после правок на сайте без переподключения
Итог
Скин из кабинета виден в руках с первого кадра.
Матч-движок EloMatch

Собственный порт MatchZy на инфраструктуру EloStore: турнирный матч управляется с сайта.
- 01Матч грузится с сайта командой css_eloload: состав, карты, серия
- 02Фазы: разминка → нож → выбор стороны → игра → перерыв → следующая карта серии
- 03Тихий whitelist ростера: чужие уходят в наблюдатели без флуда в чат
- 04Перерыв между картами настраивается в админке, все события матча уходят в ленту админки
Deathmatch EloDM

DM в стиле топовых паблик-серверов, полностью на своем коде.
- 01Своя спавн-система: телепорт на точку, где враги дальше порога, против спавн-киллов
- 02Мгновенный респавн и защита после появления, +HP за фраг, пополнение патронов
- 03Меню оружия с сохраненным лоадаутом
- 04Совместимость со скинченджером: DM не трогает нож, его выдает только EloSkins
Бродкаст-оверлей для OBS

Трансляция турнира получает живой killfeed, баннеры мультикиллов и итоги раунда.
- 01CS2 шлет Game State Integration на сайт, сервер держит последний снимок, оверлей читает поток
- 02Режиссер сравнивает снимки и находит убийства, эйсы, клатчи, бомбу, конец раунда
- 03GSI не присылает, кто кого убил: пары восстанавливаются по дельте kills у убийцы и переходу alive → dead у жертвы
- 04События гаснут сами по таймеру, даже если игра перестала слать данные
Истории с прода
Инцидент 01 · открыт
Нож в замедленной съемке
Подмена скина сбивала скорость анимаций оружия: доставание и перезарядка шли в slow-mo.
Инцидент 02 · открыт
Скин вставал только после переключения
Краска применялась после появления оружия, и игроку приходилось переключать ствол, чтобы увидеть скин.
Стек
C# · .NET · CounterStrikeSharp · Source 2 · GSI · RCON · Next.js API · PostgreSQL · SSE · systemd
