docs: переписал README/ARCHITECTURE/CONTRIBUTING/SECURITY/CHANGELOG на русский

Юзер указал что вся документация opensource-репо должна быть на русском.
Также:
- .env.example комменты на русском
- package.json description на русском
- Описания org и repo в Gitea обновлены через API
This commit is contained in:
МИН 2026-05-27 23:13:28 +03:00
parent 87444ee2c8
commit 8428cda555
7 changed files with 318 additions and 314 deletions

View File

@ -1,30 +1,30 @@
# ============================================================================
# rublox-player environment variables
# Переменные окружения rublox-player
# ============================================================================
# Copy this file to .env (`cp .env.example .env`), then edit if needed.
# Defaults below point at the public staging environment so you can run the
# player out of the box without setting up your own backend.
# Скопируй этот файл в .env (`cp .env.example .env`) и поправь при необходимости.
# Дефолты ниже указывают на публичный staging — плеер заработает сразу, без
# настройки своего бэкенда.
# Backend base URL (HTTP API).
# Leave empty to use vite-proxy in dev (http://localhost:5173 → staging).
# In production set to your origin if frontend & backend are on different hosts.
# Базовый URL HTTP-API.
# Оставь пустым чтобы использовать vite-proxy в dev (http://localhost:5173 → staging).
# В проде укажи свой origin если фронтенд и бэкенд на разных хостах.
VITE_API_BASE=
# Colyseus realtime (multiplayer) endpoints.
# These DO need to be configured for multiplayer to work.
# Public staging:
# Colyseus realtime (мультиплеер) эндпоинты.
# Эти нужно настроить чтобы мультиплеер работал.
# Публичный staging:
VITE_REALTIME_HTTP=https://dev-api.rublox.pro/api-game
VITE_REALTIME_WS=wss://dev-api.rublox.pro/api-game
# Rublox main site — where players are redirected if no auth ticket present.
# Главный сайт Рублокса — куда редиректим игроков без auth-ticket'а.
VITE_RUBLOX_HOME=https://rublox.pro/app
# Standalone mode — load a built-in sample game instead of fetching from API.
# Useful for first-run / dogfood / when backend is unreachable.
# Values: "true" | "false"
# Standalone-режим — загружает встроенный демо-проект вместо запроса к API.
# Полезно для первого запуска / разработки / когда бэкенд недоступен.
# Значения: "true" | "false"
VITE_STANDALONE=false
# Asset CDN base URL (optional). When set, .glb/.png/.mp3 are loaded from
# this URL instead of the local public/ folder. Useful in production to
# offload bandwidth to Cloudflare R2 or similar.
# CDN для ассетов (опционально). Если задан, .glb/.png/.mp3 загружаются с
# этого URL вместо локальной папки public/. Полезно в проде чтобы разгрузить
# bandwidth через Cloudflare R2 или подобное.
# VITE_ASSETS_CDN=https://cdn.rublox.pro/assets

View File

@ -1,81 +1,81 @@
# Architecture — Rublox Player
# Архитектура плеера Рублокса
How a 3D game is loaded, rendered, and synced. ~5 minutes read.
Как 3D-игра загружается, рендерится и синхронизируется. Чтение ~5 минут.
## Top-level flow
## Общий поток
```
URL = /<gameId> e.g. /265
URL = /<gameId> например /265
PlayerAuthProvider checks JWT in localStorage["player_jwt"]
OR exchanges URL #ticket=... for JWT
PlayerAuthProvider проверяет JWT в localStorage["player_jwt"]
ИЛИ обменивает URL #ticket=... на JWT
useAuth().isAuthenticated
KubikonPlayer.jsx main container, gets {projectId} from useParams
KubikonPlayer.jsx главный контейнер, читает {projectId} из useParams
├── GET /api-storys/kubikon3d/projects/{id} → project_data (JSON)
BabylonScene.create() construct Babylon engine, scene, lights, skybox
BabylonScene.create() создание движка Babylon, сцены, света, неба
GameRuntime.loadProject() parse project_data, instantiate everything:
│ - BlockManager.placeBlock() × N (Minecraft-style blocks)
│ - ModelManager.spawnModel() × N (Kenney prop GLBs)
│ - DecoManager.placeDeco() × N (terrain decorations)
│ - PrimitiveManager.add() × N (cubes/spheres/cylinders)
│ - PlayerController.spawn() (R15 character + camera)
GameRuntime.loadProject() парсинг project_data, инстанциация всего:
│ - BlockManager.placeBlock() × N (Minecraft-блоки)
│ - ModelManager.spawnModel() × N (Kenney GLB)
│ - DecoManager.placeDeco() × N (декор ландшафта)
│ - PrimitiveManager.add() × N (кубы/сферы/цилиндры)
│ - PlayerController.spawn() (R15-персонаж + камера)
ScriptSandboxWorker user JS scripts run in a Web Worker sandbox.
Exposed API: game.player, scene, ui, broadcast.
ScriptSandboxWorker пользовательские JS-скрипты в Web Worker-песочнице.
Доступный API: game.player, scene, ui, broadcast.
MultiplayerSync optional. Colyseus room joins, syncs positions.
MultiplayerSync опционально. Колyseus-комната, синк позиций.
RENDER LOOP (60 fps) scene.render() each frame
ЦИКЛ РЕНДЕРА (60 fps) scene.render() каждый кадр
```
## Key modules
## Ключевые модули
### `engine/BabylonScene.js`
Wraps Babylon `Engine` + `Scene`. Creates lighting (HemisphericLight + DirectionalLight + shadow generator), skybox, fog. Single source of truth for `scene` reference.
Обёртка над `Engine` + `Scene` из Babylon. Создаёт освещение (HemisphericLight + DirectionalLight + теневой генератор), скайбокс, туман. Единый источник правды для ссылки на `scene`.
### `engine/GameRuntime.js`
Orchestrator. Reads `project_data` (the JSON saved by the studio editor) and dispatches each item to the right manager. Has lifecycle hooks: `loadProject()`, `start()`, `pause()`, `dispose()`.
Оркестратор. Читает `project_data` (JSON, сохранённый редактором студии) и направляет каждый элемент в соответствующий менеджер. Lifecycle-хуки: `loadProject()`, `start()`, `pause()`, `dispose()`.
Also handles "external URL" resolution (`_resolveExternalUrl`) — game scripts can call `game.openUrl('/kubikon/play/12')` and it correctly resolves to the player itself or the main Rublox site.
Также обрабатывает «external URL» резолвинг (`_resolveExternalUrl`) — скрипты игры могут вызвать `game.openUrl('/kubikon/play/12')`, и URL корректно резолвится в сам плеер или на главный сайт.
### `engine/PlayerController.js`
R15 character (15-bone Mixamo rig). First-person and third-person cameras. WASD/touch input. Jumping, gravity, collision against block grid + AABB models. Spawning/respawning.
R15-персонаж (15-костный Mixamo-rig). Камеры от первого и третьего лица. Управление WASD/тач. Прыжки, гравитация, столкновения с воксельным гридом + AABB-моделями. Спавн/респавн.
Special GD modes: `setAutoRun(true)`, `setShipMode(true)` — used by Geometry Dash gamemodes (cube/ship/wave/UFO/ball/spider).
Спец-режимы для GD: `setAutoRun(true)`, `setShipMode(true)` — используются гейммодами Geometry Dash (куб/корабль/волна/НЛО/мяч/паук).
### `engine/BlockManager.js` / `TerrainVoxelBuilder.js`
Voxel terrain. Blocks are uint16 type IDs in chunked arrays. `rebuildChunk(chunkId)` does greedy meshing → single mesh per material per chunk (~40-100× fewer draw calls than naive).
Воксельный ландшафт. Блоки — uint16 type-id'ы в чанковых массивах. `rebuildChunk(chunkId)` делает greedy meshing → один меш на материал на чанк (~40-100× меньше draw call'ов чем наивно).
### `engine/ModelManager.js`
Loads `.glb` Kenney models (or designer-uploaded GLBs from `/api-storys/assets/rublox-designer/models/...`). Caches `AssetContainer` per `modelTypeId`, instantiates clones per spawn.
Загрузка `.glb`-моделей Kenney (или загруженных дизайнерами GLB из `/api-storys/assets/rublox-designer/models/...`). Кеширует `AssetContainer` по `modelTypeId`, инстанциирует клоны при каждом спавне.
### `engine/DecoManager.js`
Lightweight decorative props (rocks, plants, signs). Uses `ThinInstanceCount` for massive performance (thousands of instances → single draw call per type).
Лёгкие декоративные пропсы (камни, растения, знаки). Использует `ThinInstanceCount` для огромного перфоманса (тысячи инстансов → один draw call на тип).
### `engine/scripts/ScriptSandboxWorker.js`
User-uploaded JS scripts run in a separate Web Worker. Exposed API surface (read-only):
Пользовательские JS-скрипты выполняются в отдельном Web Worker. Доступная API-поверхность (только чтение):
```js
// In a user script:
// В скрипте игрока:
game.onTick((dt) => { ... });
game.onKey('space', () => { player.jump(); });
game.broadcast('event', payload);
@ -84,62 +84,62 @@ scene.findOne('Cube1').rotateY(0.1);
ui.set({ score: 42 });
```
Scripts CANNOT access `window`, `document`, `fetch`, `localStorage`, network. They run isolated in a Worker with a strict postMessage bridge.
Скрипты **НЕ имеют** доступа к `window`, `document`, `fetch`, `localStorage`, сети. Запускаются изолированно в Worker'е через строгий postMessage-мост.
### `engine/multiplayer/MultiplayerSync.js`
Colyseus 0.16 client. Joins a room per `gameId` if multiplayer is enabled. Syncs player positions/rotations/animations at 20 Hz. Server is at `VITE_REALTIME_WS`.
Colyseus 0.16 клиент. Подключается к комнате per `gameId` если мультиплеер включён. Синхронизирует позиции/повороты/анимации игроков на 20 Hz. Сервер по `VITE_REALTIME_WS`.
### `engine/gd/*` (Geometry Dash modules)
### `engine/gd/*` (модули Geometry Dash)
30+ classes implementing GD-style 2D autorunner gamemodes within a 3D world:
- `GdCube.js`basic jump
- `GdShip.js`gravity-flip flight
- `GdWave.js`sine-wave dash
- `GdBall.js`flip-jump ball
- `GdUfo.js`multi-tap jumps
- `GdSpider.js`instant teleport
- + portals, speedpads, spikes, finish lines, trail effects, checkpoint music
30+ классов реализующих GD-стиль 2D-автораннер-гейммоды в 3D-мире:
- `GdCube.js`обычный прыжок
- `GdShip.js`гравитация-флип, полёт
- `GdWave.js`синусоида-дэш
- `GdBall.js`флип-прыжок мячом
- `GdUfo.js`мульти-тап прыжки
- `GdSpider.js`мгновенный телепорт
- + порталы, ускорители, шипы, финишные линии, трейлы, чекпойнт-музыка
Factories for each (`GdSpikeFactory`, `GdPortalFactory`, `GdMusicFactory`, ...) live under `AdminPreview/gd*/`.
Фабрики для каждого (`GdSpikeFactory`, `GdPortalFactory`, `GdMusicFactory`...) живут в `AdminPreview/gd*/`.
## Data flow (single frame)
## Поток данных (один кадр)
```
1. INPUT keyboard/touch/gamepad → PlayerController.onInput()
2. PHYSICS gravity + velocity + collision against blocks/models
3. SCRIPTS user script onTick(dt) callbacks (in worker, asynchronous)
4. MULTIPLAYER read remote positions, lerp other players
5. RENDER Babylon scene.render() → WebGL2 draw calls
6. UI React re-renders only if game.ui.set() called (throttled 250ms)
1. ВВОД клавиатура/тач/геймпад → PlayerController.onInput()
2. ФИЗИКА гравитация + скорость + столкновения с блоками/моделями
3. СКРИПТЫ onTick(dt) колбэки пользовательских скриптов (в Worker'е, асинхронно)
4. МУЛЬТИПЛЕЕР читаем удалённые позиции, lerp других игроков
5. РЕНДЕР Babylon scene.render() → WebGL2 draw calls
6. UI React ре-рендерится только если вызвали game.ui.set() (throttle 250мс)
```
## What's NOT in the player
## Чего НЕТ в плеере
- **Editing** — that lives in [Studio](https://git.rublox.pro/rublox/studio).
- **Project listing / search / publishing** — handled by main site (`rublox.pro/app`).
- **Authentication UI** — players arrive with JWT/ticket. The player only consumes them.
- **Admin / moderation** — moved out to private repo (`disaster-recovery/` for owner).
- **Редактирование** — это в [Студии](https://git.rublox.pro/rublox/studio).
- **Лента игр / поиск / публикация** — это на главном сайте (`rublox.pro/app`).
- **Авторизация-UI** — игроки приходят с JWT/ticket. Плеер только читает их.
- **Админка / модерация** — вынесены в приватный репозиторий (`disaster-recovery/` для мейнтейнера).
## Performance hotspots (places to look first when laggy)
## Узкие места по производительности (что смотреть первым делом если тормозит)
1. **`game.ui.set()` called every frame** — React setState 60Hz tanks FPS. Throttle to 250ms with a diff check.
2. **`scene.findOne()` on init** — `sceneSnapshot` arrives via rAF; reference is null. Move into `onTick` or `setTimeout(0)`.
3. **Babylon's `blockMaterialDirtyMechanism=true`** — DON'T enable. Breaks new mesh rendering (debris, tracers).
4. **`createOrUpdateSelectionOctree()`** — same. Breaks editor preview ghosts.
5. **GLB load via `SceneLoader` instead of `AssetContainer`** — leaks materials. Use `AssetContainer` + `instantiateModelsToScene()`.
1. **`game.ui.set()` вызывается каждый кадр** — React setState 60Hz убивает FPS. Дросселируй до 250мс с diff-проверкой.
2. **`scene.findOne()` на старте** — `sceneSnapshot` приходит через rAF; ссылка будет null. Перенеси в `onTick` или `setTimeout(0)`.
3. **`blockMaterialDirtyMechanism=true` в Babylon** — НЕ включать. Ломает рендер новых мешей (debris, трейсеры).
4. **`createOrUpdateSelectionOctree()`** — то же. Ломает превью-призраки редактора.
5. **GLB-загрузка через `SceneLoader` вместо `AssetContainer`** — течёт материалами. Используй `AssetContainer` + `instantiateModelsToScene()`.
## Where to start a feature
## С чего начать новую фичу
| What you want to add | Start here |
| Что хочешь добавить | Начни здесь |
|---|---|
| New block type | `engine/CONST/blockTypes.js` + texture in `public/kubikon-assets/blocks/` |
| New scripting API | `engine/scripts/ScriptSandboxAPI.js` (add to `apiSurface`) |
| New GD gamemode | Copy `engine/gd/GdBall.js`, register in `GdGameModeRegistry.js` |
| New HUD widget | `editor-shared/GameHud.jsx` |
| New preview route for designer | `AdminPreview/` (e.g. `gdSkins/PreviewGdSkins.jsx`) |
| Multiplayer event | Colyseus schema in `engine/multiplayer/schemas/` + handler in `MultiplayerSync.js` |
| Новый тип блока | `engine/CONST/blockTypes.js` + текстура в `public/kubikon-assets/blocks/` |
| Новое API для скриптов | `engine/scripts/ScriptSandboxAPI.js` (добавь в `apiSurface`) |
| Новый GD-гейммод | Скопируй `engine/gd/GdBall.js`, зарегистрируй в `GdGameModeRegistry.js` |
| Новый HUD-виджет | `editor-shared/GameHud.jsx` |
| Превью-роут для дизайнера | `AdminPreview/` (например `gdSkins/PreviewGdSkins.jsx`) |
| Мультиплеер-событие | Colyseus-схема в `engine/multiplayer/schemas/` + хендлер в `MultiplayerSync.js` |
## License notes for contributors
## Лицензионные заметки для контрибьюторов
By contributing you agree to license your changes under AGPL-3.0 AND grant the project maintainer a non-exclusive irrevocable license to sublicense (see [CLA.md](./CLA.md)). This is required so we can offer commercial licenses to enterprises.
Контрибьютя, ты соглашаешься лицензировать свои изменения под AGPL-3.0 И предоставляешь мейнтейнеру неисключительную безотзывную лицензию на сублицензирование (см. [CLA.md](./CLA.md)). Это нужно чтобы проект мог продавать коммерческие лицензии корпорациям.

View File

@ -1,31 +1,31 @@
# Changelog
All notable changes will be documented here.
Все значимые изменения документируются здесь.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/).
## [Unreleased]
### Added
- Open-source release: AGPL-3.0 + Commercial dual license.
- Standalone mode (`VITE_STANDALONE=true`) with bundled `sample-game.json`.
- Configurable backend via `VITE_API_BASE`, `VITE_RUBLOX_HOME`, `VITE_REALTIME_*`.
- Issue & PR templates under `.gitea/`.
### Добавлено
- Open-source релиз: двойная лицензия AGPL-3.0 + Коммерческая.
- Standalone-режим (`VITE_STANDALONE=true`) с встроенным `sample-game.json`.
- Конфигурируемый бэкенд через `VITE_API_BASE`, `VITE_RUBLOX_HOME`, `VITE_REALTIME_*`.
- Шаблоны Issue и PR в `.gitea/`.
- `CONTRIBUTING.md`, `SECURITY.md`, `ARCHITECTURE.md`, `CLA.md`.
- ESLint + Prettier + EditorConfig.
### Removed
- Hard-coded URLs to `minecraftia-school.ru` (all are now env-configurable).
- Internal server IPs (`85.175.x.x`, `192.168.x.x`) from comments.
- Admin endpoints (`adminPatchProjectScript`, `adminBanPublish`, etc.) — moved to private repo.
- `frontend_deploy.py` (contained SSH credentials).
### Удалено
- Захардкоженные URL `minecraftia-school.ru` (все теперь через env).
- Внутренние IP серверов (`85.175.x.x`, `192.168.x.x`) из комментариев.
- Admin-эндпоинты (`adminPatchProjectScript`, `adminBanPublish` и т.д.) — вынесены в приватный репо.
- `frontend_deploy.py` (содержал SSH-креды).
### Security
- New `git init` removes previous commit history (which contained credentials).
- Pre-commit hook blocks pushing files with detected secret patterns.
### Безопасность
- Новый `git init` удаляет предыдущую историю коммитов (где были креды).
- Pre-commit hook блокирует пуш файлов с обнаруженными паттернами секретов.
## [0.1.0] — initial private build (pre-public)
## [0.1.0] — начальный приватный билд (до публикации)
- Vite + React 18 + Babylon 7.54.3 baseline.
- R15 character, GD gamemodes, multiplayer via Colyseus 0.16.
- Plays projects from `rublox.pro` and `player.rublox.pro`.
- Vite + React 18 + Babylon 7.54.3 базовая сборка.
- R15-персонаж, GD-гейммоды, мультиплеер через Colyseus 0.16.
- Запуск проектов с `rublox.pro` и `player.rublox.pro`.

View File

@ -1,150 +1,150 @@
# Contributing to Rublox Player
# Контрибьютинг в плеер Рублокса
Thanks for your interest! Here's everything you need to know.
Спасибо за интерес! Всё что нужно знать.
## Before your first PR
## Перед первым PR
1. **Sign the [CLA](./CLA.md)** — open `https://team.rublox.pro/developer/cla` (you need a `developer` role; ask the maintainer) OR comment `/sign-cla` on your PR.
2. **Have a Gitea account** linked via OAuth to team.rublox.pro.
3. **Add your SSH key** to Gitea profile (otherwise you push by HTTPS + password).
1. **Подпиши [CLA](./CLA.md)** — открой `https://team.rublox.pro/developer/cla` (нужна роль `developer` — попроси у мейнтейнера) ИЛИ комментарий `/sign-cla` на PR.
2. **Заведи Gitea-аккаунт** через OAuth-привязку к team.rublox.pro.
3. **Добавь SSH-ключ** в профиль Gitea (иначе пуш по HTTPS + пароль).
## Workflow
```bash
# 1. Fork or clone (you can push to a feature branch directly if you have access)
# 1. Клонируем (или форкаем — если есть доступ, можно сразу пушить в feature-ветку)
git clone ssh://git@git.rublox.pro:2222/rublox/player.git
cd player
npm install
cp .env.example .env
# 2. Create a feature branch
git checkout -b feature/short-description
# 2. Создаём feature-ветку
git checkout -b feature/короткое-описание
# 3. Make changes
npm run dev # test locally
npm run lint # check ESLint
npm run format # apply Prettier
# 3. Делаем изменения
npm run dev # проверяем локально
npm run lint # ESLint
npm run format # Prettier
# 4. Commit (Conventional Commits)
git commit -m "feat: add jump animation to GdBall"
# Other prefixes: fix:, chore:, docs:, refactor:, test:, perf:, ci:
# 4. Коммитим (Conventional Commits)
git commit -m "feat: добавить анимацию прыжка для GdBall"
# Другие префиксы: fix:, chore:, docs:, refactor:, test:, perf:, ci:
# 5. Push and open PR
git push origin feature/short-description
# Open PR via https://git.rublox.pro/rublox/player
# 5. Пушим и открываем PR
git push origin feature/короткое-описание
# Открыть PR через https://git.rublox.pro/rublox/player
```
## Code style
## Стиль кода
We use **Prettier** (auto-format) + **ESLint** (lint). The config is committed in `.prettierrc` and `.eslintrc.json`.
Используем **Prettier** (авто-формат) + **ESLint** (линт). Конфиги закоммичены в `.prettierrc` и `.eslintrc.json`.
Key rules:
- 2-space indent
- Single quotes (`'foo'`, not `"foo"`)
- Semicolons required
- Trailing comma in multi-line literals
- 100-char line width
- No `eval`, no `new Function`, no `innerHTML = ...`
- React: hooks rules enforced (`react-hooks/rules-of-hooks`)
Главные правила:
- 2-space отступ
- Одинарные кавычки (`'foo'`, не `"foo"`)
- Точки с запятой обязательны
- Trailing comma в многострочных литералах
- Ширина строки 100 символов
- Никаких `eval`, `new Function`, `innerHTML = ...`
- React: hooks-правила обязательны (`react-hooks/rules-of-hooks`)
Run before commit:
Запускай перед коммитом:
```bash
npm run format # auto-fixes most things
npm run lint # warns about the rest
npm run format # авто-фикс большинства
npm run lint # предупреждения для остального
```
A pre-commit hook (Husky, if installed) will block you if Prettier check fails.
Pre-commit-хук (Husky, если установлен) заблокирует если Prettier-чек провален.
## Branch naming
## Именование веток
| Prefix | Use for |
| Префикс | Использовать для |
|---|---|
| `feature/...` | New features |
| `fix/...` | Bug fixes |
| `chore/...` | Refactoring, deps, tooling |
| `docs/...` | Documentation only |
| `perf/...` | Performance improvements |
| `feature/...` | Новые фичи |
| `fix/...` | Багфиксы |
| `chore/...` | Рефакторинг, зависимости, тулинг |
| `docs/...` | Только документация |
| `perf/...` | Улучшения производительности |
## Commit messages (Conventional Commits)
## Commit-сообщения (Conventional Commits)
```
<type>: <short description>
<тип>: <короткое описание>
[optional body]
[опционально тело]
[optional footer: BREAKING CHANGE / Closes #N]
[опционально футер: BREAKING CHANGE / Closes #N]
```
Types: `feat`, `fix`, `chore`, `docs`, `refactor`, `test`, `perf`, `ci`, `style`.
Типы: `feat`, `fix`, `chore`, `docs`, `refactor`, `test`, `perf`, `ci`, `style`.
**Good:**
- `feat: add WaveMode to GdGameModeRegistry`
- `fix: ScriptSandbox crashes on Worker timeout`
- `perf: throttle ui.set() to 250ms with diff check`
**Хорошо:**
- `feat: добавить WaveMode в GdGameModeRegistry`
- `fix: ScriptSandbox падает при таймауте Worker`
- `perf: дросселировать ui.set() до 250мс с diff-проверкой`
**Bad:**
**Плохо:**
- `update code`
- `wip`
- `fixed stuff`
- `пофиксил всякое`
## PR template
## Шаблон PR
When you open a PR, fill in:
При открытии PR заполни:
```markdown
## What
## Что
(1-2 sentences: what does this PR do?)
(1-2 предложения: что делает этот PR?)
## Why
## Зачем
(motivation: bug report, feature request, related issue #N)
(мотивация: репорт бага, фича-реквест, связанный issue #N)
## How to test
## Как протестить
(reproducible steps a reviewer can run)
(воспроизводимые шаги для ревьюера)
## Screenshots / video (if UI change)
## Скриншоты / видео (если UI-изменение)
## Checklist
## Чек-лист
- [ ] `npm run lint` passes
- [ ] `npm run format:check` passes
- [ ] `npm run build` succeeds
- [ ] Tested locally with `npm run dev`
- [ ] Updated relevant docs (README / ARCHITECTURE / CHANGELOG)
- [ ] CLA signed
- [ ] `npm run lint` проходит
- [ ] `npm run format:check` проходит
- [ ] `npm run build` собирается
- [ ] Протестил локально через `npm run dev`
- [ ] Обновил соответствующие доки (README / ARCHITECTURE / CHANGELOG)
- [ ] CLA подписан
```
## Review process
## Процесс ревью
- The repo maintainer (МИН) reviews every PR.
- Expect feedback within **48 hours** (often same day).
- Small PRs (<300 lines changed) get reviewed fast. PRs >1000 lines will be asked to split.
- After approval, **maintainer merges** (only the maintainer has merge permission).
- After merge, an automated webhook triggers production deploy.
- Мейнтейнер репо (МИН) ревьюит каждый PR.
- Ожидай фидбек в течение **48 часов** (часто в тот же день).
- Маленькие PR (<300 строк) ревьюятся быстро. PR'ы >1000 строк попросят раздробить.
- После approval **мерджит мейнтейнер** (право merge только у него).
- После merge автоматический webhook запускает деплой в прод.
## What we won't merge
## Что не смерджим
- PRs that add new external dependencies without discussion
- PRs that touch sensitive paths (`engine/scripts/ScriptSandbox*.js`, `engine/multiplayer/*`) without security review
- PRs that break the build or lint
- PRs from contributors who haven't signed the CLA
- Massive refactors without a tracking issue discussed beforehand
- PR с новыми внешними зависимостями без обсуждения
- PR трогающие чувствительные пути (`engine/scripts/ScriptSandbox*.js`, `engine/multiplayer/*`) без security-ревью
- PR ломающие сборку или линт
- PR от контрибьюторов без подписанного CLA
- Массивные рефакторинги без заранее обсуждённого tracking-issue
## What we love
## Что любим
- Bug fixes with reproducible test cases
- Performance improvements with before/after metrics
- New `engine/gd/Gd*.js` gamemodes
- New script API additions (in `ScriptSandboxAPI.js`)
- Documentation improvements (especially examples)
- Багфиксы с воспроизводимыми тест-кейсами
- Улучшения производительности с before/after метриками
- Новые `engine/gd/Gd*.js` гейммоды
- Новые API для скриптов (в `ScriptSandboxAPI.js`)
- Улучшения документации (особенно с примерами)
## Security
## Безопасность
Found a vulnerability? **Don't open a public issue.** Email `security@rublox.pro` directly. See [SECURITY.md](./SECURITY.md).
Нашёл уязвимость? **Не открывай публичный issue.** Пиши на `security@rublox.pro` напрямую. См. [SECURITY.md](./SECURITY.md).
## Questions?
## Вопросы?
- Open an issue with the **Question** label
- Or hop into the `#разработка` channel at https://team.rublox.pro/chat
- Открой issue с лейблом **Question**
- Или приходи в канал `#разработка` на https://team.rublox.pro/chat

158
README.md
View File

@ -1,160 +1,164 @@
# Rublox Player
# Плеер Рублокса
Open-source web player for Rublox games — a Roblox-like creator platform.
Open-source веб-плеер игр Рублокса — платформы для создания 3D-игр в стиле Roblox.
Built with **Babylon.js 7** + **React 18** + **Vite 5**. Plays user-created 3D games published from [Rublox Studio](https://git.rublox.pro/rublox/studio) (separate repo).
Построен на **Babylon.js 7** + **React 18** + **Vite 5**. Запускает пользовательские игры, опубликованные из [Студии Рублокса](https://git.rublox.pro/rublox/studio) (отдельный репозиторий).
[![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-blue.svg)](./LICENSE)
[![Commercial license available](https://img.shields.io/badge/Commercial-License--available-green.svg)](./LICENSE-COMMERCIAL.md)
[![Лицензия: AGPL-3.0](https://img.shields.io/badge/%D0%9B%D0%B8%D1%86%D0%B5%D0%BD%D0%B7%D0%B8%D1%8F-AGPL--3.0-blue.svg)](./LICENSE)
[![Коммерческая лицензия](https://img.shields.io/badge/%D0%9A%D0%BE%D0%BC%D0%BC%D0%B5%D1%80%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F-%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%BD%D0%B0-green.svg)](./LICENSE-COMMERCIAL.md)
---
## Quick start (5 minutes)
## Быстрый старт (5 минут)
**Requirements:**
- Node.js 18+ and npm 10+
- A WebGL2-capable browser (Chrome 90+ / Firefox 90+ / Safari 15+)
- 4 GB RAM free (Babylon scenes are heavy)
**Требования:**
- Node.js 18+ и npm 10+
- Браузер с WebGL2 (Chrome 90+ / Firefox 90+ / Safari 15+)
- 4 ГБ свободной памяти (Babylon-сцены тяжёлые)
**Install:**
**Установка:**
```bash
git clone ssh://git@git.rublox.pro:2222/rublox/player.git
cd player
npm install
cp .env.example .env # defaults point at public staging — works out of the box
cp .env.example .env # дефолты указывают на публичный staging — работает сразу
npm run dev
```
Open `http://localhost:5173/<gameId>` — for example `http://localhost:5173/265` for our GD demo level.
Открой `http://localhost:5173/<gameId>` — например `http://localhost:5173/265` для нашего демо-уровня.
**Without a JWT** you'll see an auth-redirect screen. To bypass for local development:
1. Get a 90-day test JWT from a project maintainer (or use your own from rublox.pro).
2. In browser DevTools console:
**Без JWT** ты увидишь экран авторизации. Чтобы обойти его для локальной разработки:
1. Получи 90-дневный test-JWT у мейнтейнера (или используй свой с rublox.pro).
2. В DevTools браузера:
```js
localStorage.setItem('player_jwt', '<paste-your-jwt-here>');
localStorage.setItem('player_jwt', '<вставь-сюда-свой-jwt>');
location.reload();
```
---
## Assets (GLB models / textures / sounds)
## Ассеты (GLB-модели / текстуры / звуки)
The `public/kubikon-assets/` folder (~106 MB) is **not stored in git** to keep the repo small. Download it separately:
Папка `public/kubikon-assets/` (~106 МБ) **не хранится в git** чтобы репозиторий был лёгким. Скачать отдельно:
```bash
# Download assets bundle from the latest release:
# Скачать последнюю версию ассетов из релиза:
curl -L -o assets.zip https://git.rublox.pro/rublox/player/releases/download/latest/kubikon-assets.zip
unzip assets.zip -d public/
```
In standalone mode (see below) you don't need the assets — only the bundled sample game runs.
В standalone-режиме (см. ниже) ассеты не нужны — там работает только встроенная демо-игра.
---
## Standalone mode (no backend needed)
## Standalone-режим (без бэкенда)
Don't have a JWT? Want to try the player without any auth?
Нет JWT? Хочешь попробовать плеер без авторизации?
```bash
echo "VITE_STANDALONE=true" >> .env
npm run dev
```
Open `http://localhost:5173/sample` — loads a bundled demo project (`src/fixtures/sample-game.json`). All save/leaderboard/chat actions are no-ops.
Открой `http://localhost:5173/sample` — загрузится встроенный демо-проект (`src/fixtures/sample-game.json`). Все save/leaderboard/chat действия игнорируются.
---
## Project structure
## Структура проекта
```
src/
├── engine/ # Babylon.js engine — 81 files, ~46k lines.
│ # Self-contained: BabylonScene, GameRuntime, MultiplayerSync,
│ # PlayerController, BlockManager, DecoManager, ScriptSandbox,
│ # 30+ GD (Geometry Dash) gamemode classes.
├── KubikonPlayer/ # Player container UI: menu, chat, comments, mobile controls.
├── editor-shared/ # HUD components shared with editor: hotbar, healthbar, GUI overlay.
├── AdminPreview/ # Preview routes for designer team (skins / music / portals catalogs).
├── PreviewSkin/ # Routes /_preview-skin/<id> etc. used by team.rublox.pro 3D previews.
├── components/ # Shared UI: EmailConfirmNotice, KubikonBugReport, Leaderboard.
├── api/ # API.js (config) + Kubikon3DService.js (endpoint wrappers).
├── engine/ # Движок Babylon.js — 81 файл, ~46k строк.
│ # Самодостаточный: BabylonScene, GameRuntime,
│ # MultiplayerSync, PlayerController, BlockManager,
│ # DecoManager, ScriptSandbox, 30+ классов GD-гейммодов.
├── KubikonPlayer/ # UI-контейнер плеера: меню, чат, комменты, моб. контролы.
├── editor-shared/ # HUD-компоненты общие с редактором: хотбар, healthbar,
│ # GUI-оверлей.
├── AdminPreview/ # Превью-роуты для команды дизайнеров (каталоги скинов,
│ # музыки, порталов).
├── PreviewSkin/ # Роуты /_preview-skin/<id> и т.д. — для 3D-превью на
│ # team.rublox.pro.
├── components/ # Общий UI: EmailConfirmNotice, KubikonBugReport,
│ # Leaderboard.
├── api/ # API.js (конфиг) + Kubikon3DService.js (обёртки эндпоинтов).
├── auth/ # PlayerAuth.jsx (JWT/ticket flow), ticketExchange.js.
├── hooks/ # useDeviceType.js (mobile/tablet detection).
├── utils/ # kubikonTime.js (relative time formatting).
├── hooks/ # useDeviceType.js (детект моб./планшет).
├── utils/ # kubikonTime.js (форматирование времени).
├── App.jsx, main.jsx, LoadingScreen.jsx
└── fixtures/ # sample-game.json for VITE_STANDALONE=true
└── fixtures/ # sample-game.json для VITE_STANDALONE=true
```
For deep architecture, see [ARCHITECTURE.md](./ARCHITECTURE.md).
Подробнее об архитектуре — в [ARCHITECTURE.md](./ARCHITECTURE.md).
---
## Environment variables
## Переменные окружения
Copy `.env.example` to `.env` and edit:
Скопируй `.env.example` в `.env` и поправь:
| Variable | Default | Description |
| Переменная | Дефолт | Что означает |
|---|---|---|
| `VITE_API_BASE` | _(empty)_ | HTTP API base URL. Empty = use vite proxy (dev). |
| `VITE_REALTIME_HTTP` | `https://dev-api.rublox.pro/api-game` | Colyseus HTTP endpoint (multiplayer matchmaking). |
| `VITE_REALTIME_WS` | `wss://dev-api.rublox.pro/api-game` | Colyseus WebSocket endpoint. |
| `VITE_RUBLOX_HOME` | `https://rublox.pro/app` | Where to redirect users with no auth. |
| `VITE_STANDALONE` | `false` | Skip API, load `sample-game.json`. |
| `VITE_API_PROXY_TARGET` | `https://dev-api.rublox.pro` | (dev only) vite-proxy target for `/api-*`. |
| `VITE_API_BASE` | _(пустая)_ | Базовый URL HTTP-API. Пустой = vite-proxy (для dev). |
| `VITE_REALTIME_HTTP` | `https://dev-api.rublox.pro/api-game` | Colyseus HTTP-эндпоинт (мультиплеер-матчмейкинг). |
| `VITE_REALTIME_WS` | `wss://dev-api.rublox.pro/api-game` | Colyseus WebSocket-эндпоинт. |
| `VITE_RUBLOX_HOME` | `https://rublox.pro/app` | Куда редиректить юзеров без авторизации. |
| `VITE_STANDALONE` | `false` | Пропустить API, загрузить `sample-game.json`. |
| `VITE_API_PROXY_TARGET` | `https://dev-api.rublox.pro` | (только dev) куда vite-proxy шлёт `/api-*`. |
---
## Contributing
## Контрибьютинг
We welcome PRs! Before your first contribution:
Мы рады PR'ам! Прежде чем впервые что-то контрибьютить:
1. Read [CONTRIBUTING.md](./CONTRIBUTING.md) for code style, branch naming, PR template.
2. Sign our [CLA](./CLA.md) — required before any merge (we use a CLA bot in Gitea).
3. Open issues for bugs / feature requests via the templates in `.gitea/ISSUE_TEMPLATE/`.
1. Прочитай [CONTRIBUTING.md](./CONTRIBUTING.md) — стиль кода, именование веток, шаблон PR.
2. Подпиши [CLA](./CLA.md) — обязательно перед первым merge (в Gitea стоит CLA-бот).
3. Открывай issues для багов/предложений через шаблоны в `.gitea/ISSUE_TEMPLATE/`.
**Quick PR cycle:**
**Быстрый цикл PR:**
```bash
git checkout -b feature/your-feature
# ...code...
git checkout -b feature/моя-фича
# ...пишешь код...
npm run lint
npm run format
git commit -m "feat: add foo"
git push origin feature/your-feature
# Open PR at https://git.rublox.pro/rublox/player
git commit -m "feat: добавил фичу"
git push origin feature/моя-фича
# Открой PR на https://git.rublox.pro/rublox/player
```
---
## Common tasks
## Команды
```bash
npm run dev # Start dev server (vite, port 5173)
npm run build # Production build → build/
npm run preview # Preview production build locally
npm run dev # Dev-сервер (vite, порт 5173)
npm run build # Прод-билд → build/
npm run preview # Превью прод-билда локально
npm run lint # ESLint
npm run format # Prettier (write)
npm run format:check # Prettier (check only — used in CI)
npm run format # Prettier (записать)
npm run format:check # Prettier (только проверить — используется в CI)
```
---
## License
## Лицензия
Dual-licensed:
Двойная лицензия:
- **[AGPL-3.0-or-later](./LICENSE)** for open-source use. Forks and derivative works (including network-distributed services) MUST publish their source under the same license.
- **[Commercial License](./LICENSE-COMMERCIAL.md)** for proprietary use. Contact `maksimivankov26@yandex.ru`.
- **[AGPL-3.0-or-later](./LICENSE)** — для open-source использования. Форки и производные работы (включая сетевые сервисы) обязаны публиковать свой исходник под той же лицензией.
- **[Коммерческая лицензия](./LICENSE-COMMERCIAL.md)** — для проприетарных продуктов. Контакт: `maksimivankov26@yandex.ru`.
All contributors must sign the [CLA](./CLA.md) before their first merge.
Все контрибьюторы обязаны подписать [CLA](./CLA.md) перед первым merge.
© 2026 Иванкова Виктория Сергеевна (ИП). All rights reserved.
© 2026 Иванкова Виктория Сергеевна (ИП). Все права защищены.
---
## Links
## Ссылки
- Main site: https://rublox.pro
- Player demo: https://player.rublox.pro
- Studio (separate repo): https://git.rublox.pro/rublox/studio
- Issues & PRs: https://git.rublox.pro/rublox/player
- Security: see [SECURITY.md](./SECURITY.md)
- Главный сайт: https://rublox.pro
- Демо плеера: https://player.rublox.pro
- Студия (отдельный репо): https://git.rublox.pro/rublox/studio
- Issues и PR: https://git.rublox.pro/rublox/player
- Безопасность: см. [SECURITY.md](./SECURITY.md)

View File

@ -1,64 +1,64 @@
# Security Policy
# Политика безопасности
## Supported versions
## Поддерживаемые версии
Only the `main` branch receives security updates. Tagged releases (`v0.x`) are best-effort.
Только ветка `main` получает security-обновления. Тегированные релизы (`v0.x`) — best-effort.
## Reporting a vulnerability
## Сообщение об уязвимости
**Do NOT open a public issue for security vulnerabilities.**
**НЕ открывай публичный issue для уязвимостей безопасности.**
Vulnerabilities in this player can directly impact our production service at `player.rublox.pro` and the games that users have published. Public disclosure before a patch can lead to real harm to real users (including minors who play our games).
Уязвимости в этом плеере могут напрямую повлиять на наш продакшен `player.rublox.pro` и игры, опубликованные юзерами. Публичное раскрытие до выпуска патча может привести к реальному вреду реальным пользователям (включая несовершеннолетних, играющих в наши игры).
Please email: **`security@rublox.pro`** (read only by the project maintainer)
Пиши на: **`security@rublox.pro`** (читает только мейнтейнер проекта)
Include:
Включи в письмо:
1. A description of the issue
2. Steps to reproduce (or a proof-of-concept)
3. Affected versions / files
4. Your impact assessment (XSS / RCE / IDOR / sandbox escape / etc.)
5. Your contact for follow-up
6. Whether you want public credit after the fix (we'll add you to a Hall of Fame in CHANGELOG)
1. Описание проблемы
2. Шаги воспроизведения (или proof-of-concept)
3. Затронутые версии / файлы
4. Твою оценку воздействия (XSS / RCE / IDOR / побег из песочницы / и т.д.)
5. Твой контакт для уточнений
6. Хочешь ли публичное упоминание после фикса (добавим в Hall of Fame в CHANGELOG)
## What to expect
## Что ожидать
| Step | Time |
| Шаг | Сроки |
|---|---|
| Acknowledgement | within 24 hours |
| Severity assessment | within 3 business days |
| Fix in private branch | within 7 days for critical |
| Public patch release | when ready, with credit |
| Подтверждение получения | в течение 24 часов |
| Оценка серьёзности | в течение 3 рабочих дней |
| Фикс в приватной ветке | в течение 7 дней для критичных |
| Публичный релиз патча | когда готов, с благодарностью |
## Especially welcome
## Особенно ценные находки
The following classes of bugs are highly valued (because they can compromise users):
Следующие классы багов **высоко ценятся** (потому что могут скомпрометировать пользователей):
- **Script sandbox escape** (`engine/scripts/ScriptSandbox*.js`) — a user-uploaded game script gaining access to `window`, `document`, `fetch`, `localStorage`, or hijacking other players' sessions.
- **XSS in game-content rendering** — game titles, chat messages, comment bodies that get rendered as HTML.
- **Multiplayer message-injection** — crafted Colyseus messages causing other clients to crash or execute attacker code.
- **Auth-token leakage** — JWT or ticket appearing in URLs, query strings, console logs, error pages, or analytics events.
- **Asset-URL injection** — `url:...` prefixes (designer-uploaded models) that load arbitrary files from outside our asset bucket.
- **Побег из script-песочницы** (`engine/scripts/ScriptSandbox*.js`) — скрипт юзера получает доступ к `window`, `document`, `fetch`, `localStorage`, либо угоняет сессии других игроков.
- **XSS в рендере контента игр** — названия игр, чат-сообщения, тексты комментов рендерятся как HTML.
- **Инъекция мультиплеер-сообщений** — кастомные Colyseus-сообщения роняют других клиентов или выполняют код атакующего.
- **Утечка auth-токена** — JWT или ticket появляется в URL, query-string, console-логах, error-страницах или analytics-событиях.
- **Инъекция в asset-URL** — префиксы `url:...` (модели от дизайнеров) загружают произвольные файлы вне нашего asset-бакета.
## Things that are NOT vulnerabilities
## Что НЕ является уязвимостью
(Save your and our time — these get rejected.)
(Не теряй своё и наше время — эти отчёты отклоняются.)
- Missing `X-Frame-Options` or `Content-Security-Policy` (we know, working on it server-side).
- Self-XSS (user pasting JS into their own DevTools).
- Outdated `npm audit` warnings without a working exploit.
- Information disclosure of files in the repo (it's open-source!).
- Reports generated by automated scanners with no manual verification.
- Отсутствующий `X-Frame-Options` или `Content-Security-Policy` (знаем, работаем над этим на стороне сервера).
- Self-XSS (юзер сам вставляет JS в свой DevTools).
- Устаревшие `npm audit` warning'и без рабочего эксплойта.
- Раскрытие информации о файлах в репо (это же open-source!).
- Отчёты от автоматических сканеров без ручной проверки.
## Reward
## Награда
We're a small project. We can't pay bounties, but for any genuine vulnerability:
Мы маленький проект и не можем платить bounty, но за любую настоящую уязвимость:
- Public credit in `CHANGELOG.md` (if you want)
- Inclusion in a "Hall of Fame" section in this file
- Personal thank-you from the maintainer
- For high-impact reports: a one-time financial gift at the maintainer's discretion (rare, but possible)
- Публичное упоминание в `CHANGELOG.md` (если хочешь)
- Включение в раздел «Hall of Fame» этого файла
- Личное спасибо от мейнтейнера
- За high-impact-репорты: разовый денежный подарок по усмотрению мейнтейнера (редко, но возможно)
## Hall of Fame
_Empty so far — be the first!_
_Пока пусто — стань первым!_

View File

@ -2,7 +2,7 @@
"name": "rublox-player",
"version": "1.0.0",
"type": "module",
"description": "Open-source web player for Rublox games — a Roblox-like creator platform. Babylon.js 7 + React 18 + Vite 5.",
"description": "Open-source веб-плеер игр Рублокса — платформы создания 3D-игр в стиле Roblox. Babylon.js 7 + React 18 + Vite 5.",
"keywords": [
"rublox",
"game-player",