К содержимому
Ricklayer
RUEN
← Все кейсы

02 · Экосистема EloStore

CS2-серверы

Скинченджер, матч-движок и бродкаст

Свои игровые серверы на своем коде: скины из кабинета на сайте появляются в игре по SteamID, турниры грузятся из админки, трансляция получает живой killfeed. 3 своих плагина на C#, 1 755 строк без сторонних плагинов и 0 переключений оружия, чтобы скин встал.

Скины из кабинета

Игрок выбирает раскраску в кабинете на сайте, заходит на сервер, и она уже в руках. Здесь те же рендеры, что видит игрок в кабинете.

Рендеры из кабинета elostore.ru

AK-47 | Asiimov
01AK-47 | Asiimov
AWP | Dragon Lore
02AWP | Dragon Lore
M4A1-S | Printstream
03M4A1-S | Printstream
M4A4 | Howl
04M4A4 | Howl
AK-47 | Fire Serpent
05AK-47 | Fire Serpent
AWP | Gungnir
06AWP | Gungnir
M4A1-S | Black Lotus
07M4A1-S | Black Lotus
USP-S | Kill Confirmed
08USP-S | Kill Confirmed
AK-47 | Neon Rider
09AK-47 | Neon Rider
M4A4 | Temukau
10M4A4 | Temukau
AWP | Chromatic Aberration
11AWP | Chromatic Aberration
AK-47 | Head Shot
12AK-47 | Head Shot

Ножи и перчатки

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

Karambit | Fade
Karambit | Fade
Butterfly Knife | Fade
Butterfly Knife | Fade
M9 Bayonet | Lore
M9 Bayonet | Lore
Sport Gloves | Vice
Sport Gloves | Vice
Specialist Gloves | Crimson Kimono
Specialist Gloves | Crimson Kimono

Свой движок раскрасок

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

Интерфейс воссоздан: модель и узор из файлов игры, шейдер из вьюера движка, числа в терминале условные

0

раскраски собрал движок

0

модели оружия из файлов игры

8

стилей краски по формулам шейдера

Задача

Турнирам и скинам EloStore нужен был свой сервер, а не чужие плагины с закрытым поведением.

Задача: связать сайт и игру. Игрок настраивает все на сайте, заходит на сервер, и все уже на месте: скины, состав, фазы матча, трансляция.

Срез по слоям

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

Скинченджер EloSkins

Игрок выбирает скины оружия, ножи, перчатки, агентов и наклейки в кабинете на сайте, и они появляются в игре.

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

Итог

Скин из кабинета виден в руках с первого кадра.

Матч-движок EloMatch

Собственный порт MatchZy на инфраструктуру EloStore: турнирный матч управляется с сайта.

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

Deathmatch EloDM

DM в стиле топовых паблик-серверов, полностью на своем коде.

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

Бродкаст-оверлей для OBS

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

  1. 01CS2 шлет Game State Integration на сайт, сервер держит последний снимок, оверлей читает поток
  2. 02Режиссер сравнивает снимки и находит убийства, эйсы, клатчи, бомбу, конец раунда
  3. 03GSI не присылает, кто кого убил: пары восстанавливаются по дельте kills у убийцы и переходу alive → dead у жертвы
  4. 04События гаснут сами по таймеру, даже если игра перестала слать данные

Истории с прода

Инцидент 01 · открыт

Нож в замедленной съемке

Подмена скина сбивала скорость анимаций оружия: доставание и перезарядка шли в slow-mo.

Инцидент 02 · открыт

Скин вставал только после переключения

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

Стек

C# · .NET · CounterStrikeSharp · Source 2 · GSI · RCON · Next.js API · PostgreSQL · SSE · systemd