chore: init monorepo with launcher and server submodules

This commit is contained in:
2026-05-23 18:04:36 +03:00
commit 7a53666245
5 changed files with 337 additions and 0 deletions

View File

@@ -0,0 +1,199 @@
# Спецификация серверной части Minecraft проекта (Backend & Infrastructure)
## 1. Стек технологий
* **Бэкенд-платформа:** Go (чистый net/http с роутером github.com/go-chi/chi, для максимальной прозрачности и контроля).
* **База данных:** PostgreSQL (реляционная СУБД для надежного хранения транзакций токенов, пользователей и связей файлов).
* **Фронтенд (Сайт и Админка):** SPA на Vue.js / React / Svelte, либо классический монолит на Go-шаблонах (html/template) для максимального упрощения деплоя (всё в одном исполняемом файле).
* **Статический веб-сервер (CDN):** Nginx (занимается отдачей тяжелых файлов и проксированием API-запросов к Go-бэкенду).
---
## 2. Архитектура хранилища файлов (Content-Addressable Storage - CAS)
Для экономии места на диске сервера и клиента, а также для сквозного кэширования, все файлы модов, библиотек и ассетов хранятся по их SHA-1 хэшам.
* **Путь на сервере:** `/var/www/cdn/files/[первые два символа хэша]/[полный хэш]`
* *Пример:* Файл с хэшем `a1b2c3d4e5...` будет лежать по пути `/var/www/cdn/files/a1/b2c3d4e5...` (это предотвращает замедление файловой системы при наличии десятков тысяч файлов в одной директории).
* **URL для скачивания:** `https://cdn.myserver.com/files/a1b2c3d4e5...`
---
## 3. Схема Базы Данных (PostgreSQL)
```sql
-- Таблица пользователей
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(32) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
uuid UUID UNIQUE NOT NULL,
role VARCHAR(16) DEFAULT 'user', -- 'user', 'admin'
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица скинов и плащей (ссылки на файлы в CAS)
CREATE TABLE player_textures (
user_id INT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
skin_hash VARCHAR(40), -- SHA-1 хэш файла скина в CAS
cape_hash VARCHAR(40), -- SHA-1 хэш файла плаща в CAS
is_slim BOOLEAN DEFAULT FALSE -- модель скина (Alex/Steve)
);
-- Сессии Yggdrasil (для авторизации лаунчера и игры)
CREATE TABLE yggdrasil_sessions (
client_token UUID NOT NULL,
access_token UUID PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMP NOT NULL
);
-- Таблица модпаков (игровых серверов)
CREATE TABLE modpacks (
id SERIAL PRIMARY KEY,
slug VARCHAR(32) UNIQUE NOT NULL, -- например: 'hitech', 'magic'
name VARCHAR(64) NOT NULL,
minecraft_version VARCHAR(16) NOT NULL,
java_version INT NOT NULL, -- 8, 17, 21
server_ip VARCHAR(255) NOT NULL, -- IP:Port для добавления в servers.dat
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Единый реестр уникальных файлов (CAS)
CREATE TABLE global_files (
sha1 VARCHAR(40) PRIMARY KEY,
size_bytes BIGINT NOT NULL,
file_name VARCHAR(255) NOT NULL -- оригинальное имя файла (для истории)
);
-- Релизы лаунчера (заполняются через CI/CD)
CREATE TABLE launcher_releases (
id SERIAL PRIMARY KEY,
version VARCHAR(32) NOT NULL, -- например: '1.2.0'
os VARCHAR(16) NOT NULL, -- 'windows', 'linux', 'darwin'
arch VARCHAR(16) NOT NULL, -- 'amd64', 'arm64'
sha256 VARCHAR(64) NOT NULL, -- SHA-256 для проверки бинарника лаунчера
file_path VARCHAR(255) NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
is_mandatory BOOLEAN DEFAULT TRUE, -- принудительное обновление
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
---
## 4. Спецификация API Эндпоинтов
### 4.1. Автоматический деплой из CI/CD (Protected Route)
Эндпоинт, который вызывает твой пайплайн сборки после успешной компиляции лаунчера.
* **Маршрут:** `POST /api/admin/launcher/release`
* **Авторизация:** Заголовок `X-CI-Token: <секретный_токен_из_секретов_репозитория>`
* **Тело запроса (Multipart Form Data):**
* `version`: "1.2.0"
* `os`: "windows"
* `arch`: "amd64"
* `sha256`: "hash_of_binary..."
* `file`: (бинарный файл лаунчера)
### 4.2. Yggdrasil API (Mojang Emulation)
* `POST /authserver/authenticate` — Аутентификация по логину/паролю. Возвращает UUID и токены.
* `POST /authserver/refresh` — Обновление сессии лаунчера по `clientToken` и `accessToken`.
* `POST /authserver/validate` — Быстрая проверка токена при запуске лаунчера.
* `GET /sessionserver/session/minecraft/profile/{uuid}` — Эндпоинт, к которому обращается сам игровой клиент для загрузки скинов игроков на сервере.
### 4.3. Публичное API сайта и лаунчера
* `POST /api/web/register` — Регистрация игрока.
* `POST /api/web/login` — Логин в личный кабинет сайта.
* `POST /api/web/profile/skin` — Загрузка скина (принимает PNG, считает его SHA-1, сохраняет в `/files/` и привязывает к юзеру).
* `GET /api/launcher/latest` — Возвращает информацию о последней версии лаунчера и ссылки на скачивание для автообновления.
* `GET /api/servers.json` — Список активных модпаков для меню выбора в лаунчере.
---
## 5. Алгоритмы и Пайплайны работы
### 5.1. Пайплайн загрузки и сборки модпака (в Админ-панели)
Когда админ загружает ZIP-архив с обновлением модов/конфигов через панель управления:
```text
[Архив с модами] -> [Распаковка во временную папку]
[Обход каждого файла в цикле]
[Расчет SHA-1 хэша]
┌─────────────┴─────────────┐
▼ ▼
[Хэш ЕСТЬ в базе?] [Хэша НЕТ в базе]
│ │
│ [Копирование в CAS]
│ [/files/ab/abcdef12...]
│ │
└─────────────┬─────────────┘
[Добавление в manifest.json]
```
**Итоговый формат генерируемого `manifest.json` для лаунчера:**
```json
{
"minecraft_version": "1.21",
"java_version": 21,
"server_info": {
"name": "HiTech Server",
"ip": "play.myserver.com:25565"
},
"files": [
{
"path": "mods/jei-1.21.jar",
"hash": "a1b2c3d4e5f6...",
"size": 1048576,
"url": "https://cdn.myserver.com/files/a1b2c3d4e5f6..."
},
{
"path": "config/general.json",
"hash": "f7g8h9i0j1k2...",
"size": 1245,
"url": "https://cdn.myserver.com/files/f7g8h9i0j1k2..."
}
]
}
```
### 5.2. Автоматическое добавление сервера в игру (servers.dat)
Перед запуском игры лаунчер читает блок `server_info` из манифеста. Если в `instances/<slug>/servers.dat` отсутствует сервер с IP `server_info.ip`, лаунчер парсит этот NBT-файл и добавляет в него новую запись:
* **Имя:** `server_info.name`
* **IP:** `server_info.ip`
Это избавляет игроков от ручного ввода IP в клиенте.
### 5.3. Пайплайн CI/CD Релиза Лаунчера
```text
[Коммит/Тег в Git] -> [Сборка в CI (Windows/Linux/macOS)]
[Расчет SHA-256 для каждого]
[POST-запрос с секретным токеном]
[Go-Бэкенд сохраняет файлы]
[Обновляет версию лаунчера в БД]
[Игроки видят обновление при запуске]
```
---
## 6. Конфигурация Nginx (CDN & Static)
Для максимальной производительности Nginx настраивается на прямую отдачу файлов, минуя Go-бэкенд. Запросы к API проксируются.
* **Статика (`/files/`)**: Настраивается отдавать файлы с вечным кэшированием, так как они никогда не меняются (меняется только сам хэш в манифесте).
* **Скины (`/skins/`)**: Кэширование настраивается на меньший срок (например, 1 час), чтобы при смене скина игроки видели изменения без жесткого сброса кэша.
* **API (`/api/`, `/authserver/`)**: Все запросы перенаправляются на локальный порт Go-приложения (например, `127.0.0.1:8080`).