chore: init monorepo with launcher and server submodules
This commit is contained in:
8
.gitmodules
vendored
Normal file
8
.gitmodules
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
[submodule "launcher"]
|
||||
path = launcher
|
||||
url = ssh://git@gitea.mrixs.me:2222/Mrixs/MrixsCraft-launcher.git
|
||||
branch = master
|
||||
[submodule "server"]
|
||||
path = server
|
||||
url = ssh://git@gitea.mrixs.me:2222/Mrixs/MrixsCraft-server.git
|
||||
branch = master
|
||||
128
docs/launcher/Specification.md
Normal file
128
docs/launcher/Specification.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Спецификация архитектуры Minecraft лаунчера
|
||||
|
||||
## 1. Общие сведения
|
||||
* **Язык программирования:** Go (Golang)
|
||||
* **GUI-библиотека:** Fyne
|
||||
* **Целевые ОС:** Windows, macOS, Linux (кроссплатформенная компиляция)
|
||||
* **Тип сервера:** Приватный мультисерверный проект (с поддержкой разных модпаков и версий игры)
|
||||
|
||||
## 2. Ключевые модули лаунчера (Core Modules)
|
||||
|
||||
### 2.1. Модуль авторизации (Auth Manager)
|
||||
* **Протокол:** Yggdrasil API (кастомный сервер).
|
||||
* **Инъекция:** Использование `authlib-injector.jar` для перенаправления запросов клиента с серверов Mojang на приватный Yggdrasil-сервер.
|
||||
* **Сохранение сессии:** Локальное хранение `accessToken` и `clientToken` в зашифрованном или скрытом JSON-файле (например, `session.json`).
|
||||
* **Жизненный цикл:** При запуске лаунчер выполняет `/validate` или `/refresh`. При успехе пропускает экран логина, при неудаче запрашивает пароль.
|
||||
|
||||
### 2.2. Модуль синхронизации файлов (Sync & Download Manager)
|
||||
* **Манифест:** Скачивание `manifest.json` с описанием структуры файлов (ассеты, библиотеки, моды, конфиги).
|
||||
* **Хэширование:** Использование алгоритма **SHA-1** для сверки локальных файлов с манифестом.
|
||||
* **Многопоточность:** Асинхронная загрузка недостающих/поврежденных файлов (горутины + воркер-пулы).
|
||||
* **Разрешение конфликтов:** Если в папке `mods/` найден файл, которого нет в манифесте, он **не удаляется безвозвратно**, а перемещается в папку `mods_backup/` для предотвращения крашей игры (Soft Deletion/Self-healing).
|
||||
|
||||
### 2.3. Модуль управления Java (JRE Manager)
|
||||
* **Изоляция:** Лаунчер загружает и использует собственные портативные версии Java (8, 17, 21), не завися от установленной в ОС.
|
||||
* **Логика:** Манифест сервера указывает требуемую версию Java (например, `java_version: 21`). Лаунчер проверяет наличие папки `Java/21/bin/java` внутри своей рабочей директории (см. раздел 4). Если ее нет — скачивает архив, распаковывает и выдает права на исполнение (для UNIX-систем).
|
||||
|
||||
### 2.4. Модуль запуска (Launch Engine)
|
||||
* **Агностичность:** Лаунчер не привязан к конкретному Mod Loader'у (Vanilla, Fabric, Forge).
|
||||
* **Генерация аргументов:** Манифест предоставляет шаблоны `mainClass` и `gameArgs` (массив строк).
|
||||
* **Интерполяция:** Замена псевдопеременных в строке запуска перед стартом:
|
||||
* `${player_name}` -> Никнейм игрока
|
||||
* `${auth_uuid}` -> UUID сессии
|
||||
* `${auth_access_token}` -> Токен Yggdrasil
|
||||
* `${classpath}` -> Склейка путей ко всем `.jar` библиотекам
|
||||
* Обязательное внедрение аргумента: `-javaagent:<путь>/authlib-injector.jar=<URL_сервера>`.
|
||||
|
||||
### 2.5. Модуль автообновления (Self-Updater)
|
||||
* **Библиотека:** `github.com/cloudflare/go-selfupdate`.
|
||||
* **Механика:** Сравнение текущей версии с версией на сервере API. Скачивание нового бинарника, переименование текущего исполняемого файла в `.old` (обход блокировки Windows) и перезапуск программы.
|
||||
|
||||
---
|
||||
|
||||
## 3. Пользовательский интерфейс (UI - Fyne)
|
||||
|
||||
Основан на компоновке `BorderLayout` со следующими зонами:
|
||||
|
||||
| Зона (Layout) | Элементы виджетов (Fyne Widgets) | Описание логики |
|
||||
| :--- | :--- | :--- |
|
||||
| **Left (Лево)** | `widget.List` / `container.VBox` | Вертикальный список серверов (модпаков). Содержит иконки и названия. При выборе меняет контент центральной зоны. |
|
||||
| **Center (Центр)**| `widget.RichText`, `canvas.Image` | Фоновое изображение выбранного сервера. Поверх него — Markdown-карточка с новостями/патчноутами. |
|
||||
| **Bottom (Низ)** | `BorderLayout` (вложенный) | Панель управления (Навигация и статус). |
|
||||
| *Bottom-Left* | `canvas.Image`, `widget.Label` | Аватарка (лицо из скина 8x8) и никнейм. Кнопка "Выйти". |
|
||||
| *Bottom-Center*| `widget.ProgressBar` | Полоса загрузки (показывает прогресс скачивания файлов). Скрыта, если нет активных загрузок. |
|
||||
| *Bottom-Right* | `widget.Button` | Кнопка «Настройки» (шестеренка) и большая акцентная кнопка «PLAY». |
|
||||
|
||||
### 3.1. Экран настроек (Модальное окно)
|
||||
* **ОЗУ:** Слайдер (`widget.Slider`) для выбора выделяемой оперативной памяти (от 1 ГБ до максимума физической ОЗУ пользователя). Конвертируется в флаги `-Xms` и `-Xmx`.
|
||||
* **Доп. аргументы:** Текстовое поле (`widget.Entry`) для пользовательских флагов JVM (например, настройки Garbage Collector).
|
||||
|
||||
---
|
||||
|
||||
## 4. Структура файловой системы (Клиентская часть)
|
||||
|
||||
Кастомная корневая директория, зависящая от ОС:
|
||||
* **Windows:** `%AppData%\Roaming\MrixsCraft\`
|
||||
* **macOS:** `~/Library/Application Support/MrixsCraft/`
|
||||
* **Linux:** `~/.MrixsCraft/`
|
||||
|
||||
Внутренняя иерархия папок:
|
||||
```text
|
||||
MrixsCraft/
|
||||
├── launcher.exe # Исполняемый файл лаунчера
|
||||
├── launcher.json # Настройки лаунчера (ОЗУ, выбранный сервер)
|
||||
├── session.json # Токены авторизации Yggdrasil
|
||||
├── authlib-injector.jar # Перехватчик авторизации
|
||||
├── Java/ # Портативные версии Java
|
||||
│ ├── 8/
|
||||
│ │ └── bin/java
|
||||
│ ├── 17/
|
||||
│ │ └── bin/java
|
||||
│ └── 21/
|
||||
│ └── bin/java
|
||||
├── assets/ # Общие ресурсы игры (звуки, текстуры), размещаются здесь для совместимости с игрой
|
||||
├── libraries/ # Общие библиотеки (LWJGL, утилиты), размещаются здесь для совместимости с игрой
|
||||
└── instances/ # Изолированные клиенты (модпаки)
|
||||
├── HiTech_1_21/
|
||||
│ ├── mods/ # Моды (проверяются SHA-1)
|
||||
│ ├── mods_backup/ # Сюда скидываются неизвестные моды
|
||||
│ ├── config/ # Конфигурации
|
||||
│ └── resourcepacks/
|
||||
└── Vanilla_1_20/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Требования к серверной части (API & CDN)
|
||||
|
||||
Для корректной работы лаунчера на сервере должны быть реализованы следующие эндпоинты:
|
||||
|
||||
1. **Yggdrasil API:** `/authserver/authenticate`, `/authserver/refresh`, `/authserver/validate`.
|
||||
2. **Обновление лаунчера:** GET `/api/launcher/latest` -> Возвращает версию и прямую ссылку на бинарники (Win, Mac, Lin).
|
||||
3. **Список серверов:** GET `/api/servers.json` -> Отдает массив доступных модпаков.
|
||||
4. **Манифест сервера:** GET `/api/instances/hitech/manifest.json` -> Отдает полный граф файлов с хэшами SHA-1, путями и параметрами запуска.
|
||||
5. **Файловый хостинг (CDN):** Раздача статики (модов, ассетов, библиотек).
|
||||
|
||||
---
|
||||
|
||||
## 6. Предлагаемая структура проекта (Go Packages)
|
||||
|
||||
Для чистоты кода рекомендуется использовать стандартный паттерн структуры Go-приложений:
|
||||
|
||||
```text
|
||||
/cmd/launcher/
|
||||
└── main.go # Точка входа, инициализация Fyne приложения
|
||||
/internal/
|
||||
├── auth/ # Логика Yggdrasil, токены, профили
|
||||
├── config/ # Чтение/запись launcher.json и системных путей
|
||||
├── fetcher/ # HTTP-клиент, скачивание файлов, проверка SHA-1
|
||||
├── java/ # Определение ОС, скачивание и распаковка JRE
|
||||
├── launch/ # Парсинг manifest.json, интерполяция строк, exec.Command
|
||||
├── selfupdate/ # Интеграция библиотеки автообновления лаунчера
|
||||
└── ui/ # Код Fyne интерфейса
|
||||
├── components/ # Отдельные виджеты (аватарка, прогресс-бар)
|
||||
├── screens/ # Экраны (Логин, Главное меню, Настройки)
|
||||
└── theme/ # Кастомная тема Fyne (цвета, шрифты)
|
||||
/pkg/
|
||||
└── utils/ # Вспомогательные функции (вычисление хэша, парсинг zip)
|
||||
```
|
||||
199
docs/server/Specification.md
Normal file
199
docs/server/Specification.md
Normal 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`).
|
||||
1
launcher
Submodule
1
launcher
Submodule
Submodule launcher added at 320f009658
1
server
Submodule
1
server
Submodule
Submodule server added at 551c75a232
Reference in New Issue
Block a user