Створення платформи матчів CS2 для нашої компанії друзів

У нас є невелика спільнота CS2 — лише жменька друзів, які регулярно грають разом, — і стандартний матчмейкінг ніколи по-справжньому не відповідав тому, як ми хотіли грати. Тому я побудував повний стек навколо цього: плагін для сервера CS2, вебплатформу та мобільний застосунок, які всі спілкуються з одним бекендом. Три проєкти, одна екосистема.

Три складові

Плагін сервера CS2 (C# / .NET 8) — Побудований на CounterStrikeSharp, цей плагін працює всередині виділеного сервера CS2. Він керує змагальним процесом матчу: розминкою, системою .ready, ножовими раундами, технічними паузами, серіями з кількох карт, зміною сторін у перерві та запасним «AIM-режимом», коли матч не активний. Він отримує конфігурації матчу за URL, який надає вебсервер, і передає кожну важливу подію — вбивства зі зброєю та позицією, результати раундів, чат, зміни життєвого циклу — у MySQL.

Вебплатформа (Laravel 13 + Vue 3 + Tailwind v4) — мозок усієї системи. Гравці входять через Steam і Discord (Laravel Socialite), створюють лобі, проводять вето карт і дивляться матчі наживо. На фронтенді — жодного HTTP-полінгу: кожна зміна стану — статус лобі, прогрес запуску сервера, бан карти, живе табло — надсилається в реальному часі через WebSockets за допомогою Laravel Reverb і Laravel Echo. Планувальник надсилає оновлення рахунку раз на хвилину, обробники черг займаються трансляціями, а Sanctum захищає мобільне API. Історія матчів, статистика гравців і деталі раундів — усе це відображається з тих самих даних, які плагін записує до MySQL.

Мобільний застосунок (Kotlin Multiplatform + Compose Multiplatform) — одна кодова база на Kotlin для Android та iOS. Він спілкується з бекендом Laravel через те саме API, захищене Sanctum, і підписується на ті самі канали Reverb, що й сайт, тому бан карти, який стається на чийомусь ноутбуці, миттєво з'являється у телефоні товариша по команді. Пуш-сповіщення надсилаються через FCM (Android) і APNs (iOS) для таких подій, як початок вето, готовність матчу та переходи життєвого циклу — це обробляють laravel-notification-channels/fcm і …/apn на боці сервера.

Як це все з'єднано

Плагін завантажує конфігурацію з бекенду Laravel, коли починається матч, записує кожну подію назад у MySQL, і та сама база даних живить як вебінтерфейс, так і мобільний застосунок — обидва підписані на однакові канали Reverb, тому всі клієнти залишаються синхронізованими без потреби щось оновлювати вручну.

Технологічний стек коротко

Шар Технологія
Плагін ігрового сервера C#, .NET 8, CounterStrikeSharp, MySqlConnector
Бекенд PHP 8.5, Laravel 13, Reverb, Sanctum, Socialite (Steam + Discord)
Фронтенд Vue 3, Tailwind v4, Vite, Laravel Echo, Chart.js, vue-i18n (EN/UK/PL/BE)
Мобільний застосунок Kotlin Multiplatform, Compose Multiplatform, FCM, APNs
Реальний час Reverb (WebSockets) → Echo у вебі + KMP-клієнт
Тестування Pest 4 (PHP), Pint для форматування

Навіщо це створювати

Чесно? Це просто для розваги і для людей, з якими я граю. Але це перетворилося на гарну вправу від початку до кінця — нативне розширення для ігрового сервера, вебзастосунок реального часу і кросплатформений мобільний клієнт, які всі мають єдине джерело правди. Кожен матч, який ми граємо, також одночасно тестує кожен шар стеку, а це найкращий тип зворотного зв'язку.

Скріншоти

1 / 5