Skip to content

Repository files navigation

SVO Game

Многомодульный Minecraft-проект для ивент-сервера SvoCraft: прокси на Velocity, Forge-мод игрового сервера с несколькими игровыми режимами (CTF, Extraction/SVOEX (Undone)), обвязка для лобби и деплой-инструменты.

Ключевая идея архитектуры - ивент не переключается "на лету". Старт режима — это управляемый рестарт игрового сервера: прокси просит подготовить карту, отдельный загрузчик (startup) перезаливает мир, после чего Forge-мод поднимает выбранный режим.

Состав репозитория

Модуль Роль
shared Общие Kotlin-модели: MapId, PlayerId, роли команд, состояния матча, Redis-каналы (RedisPaths), конфиги. Используется всеми остальными модулями.
velocityPlugin Плагин прокси (Velocity). Команды /svo ..., роутинг игроков между Lobby и игровым сервером, состояние ивента, запросы к игровому серверу через Redis.
gameMod Forge-мод игрового сервера. Держит рантайм активного режима, обработчики событий Minecraft, state machine матча, CTF и SVOEX/Extraction контент.
startup Отдельный JVM-загрузчик, который стартует до Minecraft-сервера: читает lock-файл, при необходимости вайпает и распаковывает карту, пишет mapinfo.json, запускает server.jar.
duelPitMod Лёгкий Forge-мод для лобби: публикует в Redis список игроков в дуэльной яме.
runtime Вспомогательные общие библиотеки рантайма, шарятся между модами.
docs/ Подробные архитектурные заметки (event-architecture.md, gamemode-architecture.md, svoex-singleplayer.md) и AGENTS.md-заметки в gameMod/.
scripts/deploy_lifehosting.py Сборка и деплой готовых jar-ов на боевые серверы (Pterodactyl/LifeHosting).

Как это работает: пайплайн запуска ивента

sequenceDiagram
    participant Admin as Admin
    participant Proxy as Velocity (proxy)
    participant Redis as Redis
    participant Game as gameMod
    participant Startup as startup
    participant Lobby as Lobby

    Admin->>Proxy: /svo start <mode> <map>
    Proxy->>Redis: PregameWipeRequest
    Redis->>Game: PregameWipeRequest
    Game->>Game: пишет svo.json.lock, State = AwaitingWipe
    Game->>Game: просит рестарт процесса
    Startup->>Startup: читает lock, вайпает world, распаковывает карту
    Startup->>Startup: пишет mapinfo.json
    Startup->>Game: запускает Forge-сервер заново
    Game->>Redis: PregameWipeResponse(success)
    Redis->>Proxy: PregameWipeResponse(success)
    Proxy->>Redis: PrepareGameRequest (roster/teams)
    Redis->>Game: PrepareGameRequest
    Game->>Game: создаёт OngoingGame, State = InGame
    Game->>Redis: PrepareGameResponse
    Redis->>Proxy: PrepareGameResponse
    Proxy->>Lobby: телепортирует игроков на игровой сервер
Loading

Транспорт сейчас — Redis (см. shared/.../redis/RedisPaths.kt), но он спрятан за интерфейсами connector'ов и может быть заменён.

Полное описание — в docs/event-architecture.md и docs/gamemode-architecture.md.

Изоляция режимов

gameMod собирает все режимы в один jar (CTF и Extraction регистрируются одновременно), но активен только один. Изоляция держится на runtime-проверках (ActiveModeGuard), а не на загрузке классов — при добавлении нового обработчика события/команды/mixin'а обязателен guard по активному режиму. Подробности и текущий технический долг — в gameMod/AGENTS.md.

Требуемая архитектура окружения

Для полноценного запуска ивента нужны минимум 4 процесса/сервера:

  1. Redis — шина сообщений и хранилище состояния/каталога карт между proxy и игровым сервером.
  2. Proxy (Velocity 3.4 + velocityPlugin) — точка входа игроков, админ-команды /svo ....
  3. Lobby (любой Paper/Velocity-совместимый сервер + при желании duelPitMod) — сервер ожидания.
  4. Event/Game server (Forge 1.20.1 + gameMod, запускается через startup, а не напрямую) — сервер, на котором проходит матч.
flowchart TB
    Players["Игроки"] --> Proxy["Proxy\nVelocity + velocityPlugin"]
    Proxy <-- Redis --> Lobby["Lobby"]
    Proxy <-- Redis --> Event["Event server\nForge + gameMod (CTF / Extraction)"]
    Lobby <-- Redis --> Event
    Event -->|запускается через| Startup["startup\n(вайп/распаковка карты)"]
Loading

Версии: Minecraft 1.20.1, Forge 47.4.8, Velocity 3.4.0-SNAPSHOT, Kotlin 1.9.23, Java 17 для игрового сервера / 21 для прокси-плагина (требование Velocitab).

Сборка

Требуется JDK 17+ (сборка сама выбирает toolchain через foojay-resolver).

./gradlew build

Задача collectArtifacts (навешена на assemble/build) собирает готовые jar-ы всех модулей в build/artifacts/:

  • svocraft-*.jargameMod (игровой сервер, Forge-мод).
  • svoruntime-*.jarruntime.
  • duel_pit-*.jarduelPitMod (лобби).
  • velocityPlugin-*.jar — плагин прокси.
  • startup.jar / startup-all.jar — загрузчик игрового сервера.

Точечная сборка модуля: ./gradlew :gameMod:build, ./gradlew :velocityPlugin:build и т.д.

Локальный запуск

  • Прокси: ./gradlew :velocityPlugin:runVelocity — поднимает тестовый Velocity с уже подключенным плагином.
  • Игровой сервер (Forge): стандартный ForgeGradle ран, например ./gradlew :gameMod:runServer (рабочая директория gameMod/run/).
  • Redis: локально, например docker run -p 6379:6379 redis.

Перед первым запуском:

cp local.properties.example local.properties   # креды Reposilite, если используется приватный maven
cp duelPitMod/duel_pit_mod.json.example duelPitMod/run/config/duel_pit_mod.json  # опционально, для duelPitMod

Конфигурация

  • gameMod: ServerConfig (создаётся в рабочей директории мода) — enabled, autoDisableInSingleplayer, redisUrl, mapsConfigPath, restartParam, testMode. В одиночной игре/на клиенте рантайм ивента автоматически выключен.
  • velocityPlugin: SvoVelocityConfiglobbyServerName, gameServerName, redisUrl, backendToken/backendBaseUrl, настройки дуэлей.
  • startup: maps.json (каталог карт: архив, respawn-точки, safezone, JVM-аргументы сервера) и svo.json.lock (какую карту грузить, нужен ли вайп, какой режим). Оба файла генерируются с дефолтами при первом запуске, если отсутствуют.
  • duelPitMod: duel_pit_mod.json — URL Redis и настройки частиц.

Важно: игровой сервер запускается только через startup (java -jar startup-all.jar), не напрямую через server.jar — иначе вайп карты и запись mapinfo.json не произойдут.

Игровые режимы

  • CTF — команды Attack/Defense/Spectators, фазы Preparation (15 мин) → Game (60 мин) → возможный Overtime, захват флага.
  • Extraction (SVOEX) (Undone) — режим по отрядам с лутом, ревайвом, бонус-контрактами и точками эвакуации.

Добавление нового режима описано пошагово в docs/event-architecture.md (раздел «What must be designed for a new event mode») и в gameMod/AGENTS.md (раздел "Adding a new mode safely").

Документация

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages