Многомодульный 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: телепортирует игроков на игровой сервер
Транспорт сейчас — 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 процесса/сервера:
- Redis — шина сообщений и хранилище состояния/каталога карт между proxy и игровым сервером.
- Proxy (Velocity 3.4 +
velocityPlugin) — точка входа игроков, админ-команды/svo .... - Lobby (любой Paper/Velocity-совместимый сервер + при желании
duelPitMod) — сервер ожидания. - 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(вайп/распаковка карты)"]
Версии: 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-*.jar—gameMod(игровой сервер, Forge-мод).svoruntime-*.jar—runtime.duel_pit-*.jar—duelPitMod(лобби).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 # опционально, для duelPitModgameMod:ServerConfig(создаётся в рабочей директории мода) —enabled,autoDisableInSingleplayer,redisUrl,mapsConfigPath,restartParam,testMode. В одиночной игре/на клиенте рантайм ивента автоматически выключен.velocityPlugin:SvoVelocityConfig—lobbyServerName,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").
docs/event-architecture.md— event-пайплайн, Redis-контракты, state machine, правила CTF.docs/gamemode-architecture.md— архитектура игровых режимов.docs/extraction_mode_agent_task.md— постановка задачи по режиму Extraction.docs/svoex-singleplayer.md— особенности SVOEX в одиночной игре.gameMod/AGENTS.md— детальная ментальная модельgameMod: composition root, лаунч-путь, гварды, известные технические долги.