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. # Скопируй этот файл в .env (`cp .env.example .env`) и поправь при необходимости.
# Defaults below point at the public staging environment so you can run the # Дефолты ниже указывают на публичный staging — плеер заработает сразу, без
# player out of the box without setting up your own backend. # настройки своего бэкенда.
# Backend base URL (HTTP API). # Базовый URL HTTP-API.
# Leave empty to use vite-proxy in dev (http://localhost:5173 → staging). # Оставь пустым чтобы использовать vite-proxy в dev (http://localhost:5173 → staging).
# In production set to your origin if frontend & backend are on different hosts. # В проде укажи свой origin если фронтенд и бэкенд на разных хостах.
VITE_API_BASE= VITE_API_BASE=
# Colyseus realtime (multiplayer) endpoints. # Colyseus realtime (мультиплеер) эндпоинты.
# These DO need to be configured for multiplayer to work. # Эти нужно настроить чтобы мультиплеер работал.
# Public staging: # Публичный staging:
VITE_REALTIME_HTTP=https://dev-api.rublox.pro/api-game VITE_REALTIME_HTTP=https://dev-api.rublox.pro/api-game
VITE_REALTIME_WS=wss://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 VITE_RUBLOX_HOME=https://rublox.pro/app
# Standalone mode — load a built-in sample game instead of fetching from API. # Standalone-режим — загружает встроенный демо-проект вместо запроса к API.
# Useful for first-run / dogfood / when backend is unreachable. # Полезно для первого запуска / разработки / когда бэкенд недоступен.
# Values: "true" | "false" # Значения: "true" | "false"
VITE_STANDALONE=false VITE_STANDALONE=false
# Asset CDN base URL (optional). When set, .glb/.png/.mp3 are loaded from # CDN для ассетов (опционально). Если задан, .glb/.png/.mp3 загружаются с
# this URL instead of the local public/ folder. Useful in production to # этого URL вместо локальной папки public/. Полезно в проде чтобы разгрузить
# offload bandwidth to Cloudflare R2 or similar. # bandwidth через Cloudflare R2 или подобное.
# VITE_ASSETS_CDN=https://cdn.rublox.pro/assets # 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"] PlayerAuthProvider проверяет JWT в localStorage["player_jwt"]
OR exchanges URL #ticket=... for JWT ИЛИ обменивает URL #ticket=... на JWT
useAuth().isAuthenticated useAuth().isAuthenticated
KubikonPlayer.jsx main container, gets {projectId} from useParams KubikonPlayer.jsx главный контейнер, читает {projectId} из useParams
├── GET /api-storys/kubikon3d/projects/{id} → project_data (JSON) ├── 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: GameRuntime.loadProject() парсинг project_data, инстанциация всего:
│ - BlockManager.placeBlock() × N (Minecraft-style blocks) │ - BlockManager.placeBlock() × N (Minecraft-блоки)
│ - ModelManager.spawnModel() × N (Kenney prop GLBs) │ - ModelManager.spawnModel() × N (Kenney GLB)
│ - DecoManager.placeDeco() × N (terrain decorations) │ - DecoManager.placeDeco() × N (декор ландшафта)
│ - PrimitiveManager.add() × N (cubes/spheres/cylinders) │ - PrimitiveManager.add() × N (кубы/сферы/цилиндры)
│ - PlayerController.spawn() (R15 character + camera) │ - PlayerController.spawn() (R15-персонаж + камера)
ScriptSandboxWorker user JS scripts run in a Web Worker sandbox. ScriptSandboxWorker пользовательские JS-скрипты в Web Worker-песочнице.
Exposed API: game.player, scene, ui, broadcast. Доступный 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` ### `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` ### `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` ### `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` ### `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` ### `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` ### `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` ### `engine/scripts/ScriptSandboxWorker.js`
User-uploaded JS scripts run in a separate Web Worker. Exposed API surface (read-only): Пользовательские JS-скрипты выполняются в отдельном Web Worker. Доступная API-поверхность (только чтение):
```js ```js
// In a user script: // В скрипте игрока:
game.onTick((dt) => { ... }); game.onTick((dt) => { ... });
game.onKey('space', () => { player.jump(); }); game.onKey('space', () => { player.jump(); });
game.broadcast('event', payload); game.broadcast('event', payload);
@ -84,62 +84,62 @@ scene.findOne('Cube1').rotateY(0.1);
ui.set({ score: 42 }); 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` ### `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: 30+ классов реализующих GD-стиль 2D-автораннер-гейммоды в 3D-мире:
- `GdCube.js`basic jump - `GdCube.js`обычный прыжок
- `GdShip.js`gravity-flip flight - `GdShip.js`гравитация-флип, полёт
- `GdWave.js`sine-wave dash - `GdWave.js`синусоида-дэш
- `GdBall.js`flip-jump ball - `GdBall.js`флип-прыжок мячом
- `GdUfo.js`multi-tap jumps - `GdUfo.js`мульти-тап прыжки
- `GdSpider.js`instant teleport - `GdSpider.js`мгновенный телепорт
- + portals, speedpads, spikes, finish lines, trail effects, checkpoint music - + порталы, ускорители, шипы, финишные линии, трейлы, чекпойнт-музыка
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() 1. ВВОД клавиатура/тач/геймпад → PlayerController.onInput()
2. PHYSICS gravity + velocity + collision against blocks/models 2. ФИЗИКА гравитация + скорость + столкновения с блоками/моделями
3. SCRIPTS user script onTick(dt) callbacks (in worker, asynchronous) 3. СКРИПТЫ onTick(dt) колбэки пользовательских скриптов (в Worker'е, асинхронно)
4. MULTIPLAYER read remote positions, lerp other players 4. МУЛЬТИПЛЕЕР читаем удалённые позиции, lerp других игроков
5. RENDER Babylon scene.render() → WebGL2 draw calls 5. РЕНДЕР Babylon scene.render() → WebGL2 draw calls
6. UI React re-renders only if game.ui.set() called (throttled 250ms) 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). - **Редактирование** — это в [Студии](https://git.rublox.pro/rublox/studio).
- **Project listing / search / publishing** — handled by main site (`rublox.pro/app`). - **Лента игр / поиск / публикация** — это на главном сайте (`rublox.pro/app`).
- **Authentication UI** — players arrive with JWT/ticket. The player only consumes them. - **Авторизация-UI** — игроки приходят с JWT/ticket. Плеер только читает их.
- **Admin / moderation** — moved out to private repo (`disaster-recovery/` for owner). - **Админка / модерация** — вынесены в приватный репозиторий (`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. 1. **`game.ui.set()` вызывается каждый кадр** — React setState 60Hz убивает FPS. Дросселируй до 250мс с diff-проверкой.
2. **`scene.findOne()` on init** — `sceneSnapshot` arrives via rAF; reference is null. Move into `onTick` or `setTimeout(0)`. 2. **`scene.findOne()` на старте** — `sceneSnapshot` приходит через rAF; ссылка будет null. Перенеси в `onTick` или `setTimeout(0)`.
3. **Babylon's `blockMaterialDirtyMechanism=true`** — DON'T enable. Breaks new mesh rendering (debris, tracers). 3. **`blockMaterialDirtyMechanism=true` в Babylon** — НЕ включать. Ломает рендер новых мешей (debris, трейсеры).
4. **`createOrUpdateSelectionOctree()`** — same. Breaks editor preview ghosts. 4. **`createOrUpdateSelectionOctree()`** — то же. Ломает превью-призраки редактора.
5. **GLB load via `SceneLoader` instead of `AssetContainer`** — leaks materials. Use `AssetContainer` + `instantiateModelsToScene()`. 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/` | | Новый тип блока | `engine/CONST/blockTypes.js` + текстура в `public/kubikon-assets/blocks/` |
| New scripting API | `engine/scripts/ScriptSandboxAPI.js` (add to `apiSurface`) | | Новое API для скриптов | `engine/scripts/ScriptSandboxAPI.js` (добавь в `apiSurface`) |
| New GD gamemode | Copy `engine/gd/GdBall.js`, register in `GdGameModeRegistry.js` | | Новый GD-гейммод | Скопируй `engine/gd/GdBall.js`, зарегистрируй в `GdGameModeRegistry.js` |
| New HUD widget | `editor-shared/GameHud.jsx` | | Новый HUD-виджет | `editor-shared/GameHud.jsx` |
| New preview route for designer | `AdminPreview/` (e.g. `gdSkins/PreviewGdSkins.jsx`) | | Превью-роут для дизайнера | `AdminPreview/` (например `gdSkins/PreviewGdSkins.jsx`) |
| Multiplayer event | Colyseus schema in `engine/multiplayer/schemas/` + handler in `MultiplayerSync.js` | | Мультиплеер-событие | 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 # 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] ## [Unreleased]
### Added ### Добавлено
- Open-source release: AGPL-3.0 + Commercial dual license. - Open-source релиз: двойная лицензия AGPL-3.0 + Коммерческая.
- Standalone mode (`VITE_STANDALONE=true`) with bundled `sample-game.json`. - Standalone-режим (`VITE_STANDALONE=true`) с встроенным `sample-game.json`.
- Configurable backend via `VITE_API_BASE`, `VITE_RUBLOX_HOME`, `VITE_REALTIME_*`. - Конфигурируемый бэкенд через `VITE_API_BASE`, `VITE_RUBLOX_HOME`, `VITE_REALTIME_*`.
- Issue & PR templates under `.gitea/`. - Шаблоны Issue и PR в `.gitea/`.
- `CONTRIBUTING.md`, `SECURITY.md`, `ARCHITECTURE.md`, `CLA.md`. - `CONTRIBUTING.md`, `SECURITY.md`, `ARCHITECTURE.md`, `CLA.md`.
- ESLint + Prettier + EditorConfig. - ESLint + Prettier + EditorConfig.
### Removed ### Удалено
- Hard-coded URLs to `minecraftia-school.ru` (all are now env-configurable). - Захардкоженные URL `minecraftia-school.ru` (все теперь через env).
- Internal server IPs (`85.175.x.x`, `192.168.x.x`) from comments. - Внутренние IP серверов (`85.175.x.x`, `192.168.x.x`) из комментариев.
- Admin endpoints (`adminPatchProjectScript`, `adminBanPublish`, etc.) — moved to private repo. - Admin-эндпоинты (`adminPatchProjectScript`, `adminBanPublish` и т.д.) — вынесены в приватный репо.
- `frontend_deploy.py` (contained SSH credentials). - `frontend_deploy.py` (содержал SSH-креды).
### Security ### Безопасность
- New `git init` removes previous commit history (which contained credentials). - Новый `git init` удаляет предыдущую историю коммитов (где были креды).
- Pre-commit hook blocks pushing files with detected secret patterns. - Pre-commit hook блокирует пуш файлов с обнаруженными паттернами секретов.
## [0.1.0] — initial private build (pre-public) ## [0.1.0] — начальный приватный билд (до публикации)
- Vite + React 18 + Babylon 7.54.3 baseline. - Vite + React 18 + Babylon 7.54.3 базовая сборка.
- R15 character, GD gamemodes, multiplayer via Colyseus 0.16. - R15-персонаж, GD-гейммоды, мультиплеер через Colyseus 0.16.
- Plays projects from `rublox.pro` and `player.rublox.pro`. - Запуск проектов с `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. 1. **Подпиши [CLA](./CLA.md)** — открой `https://team.rublox.pro/developer/cla` (нужна роль `developer` — попроси у мейнтейнера) ИЛИ комментарий `/sign-cla` на PR.
2. **Have a Gitea account** linked via OAuth to team.rublox.pro. 2. **Заведи Gitea-аккаунт** через OAuth-привязку к team.rublox.pro.
3. **Add your SSH key** to Gitea profile (otherwise you push by HTTPS + password). 3. **Добавь SSH-ключ** в профиль Gitea (иначе пуш по HTTPS + пароль).
## Workflow ## Workflow
```bash ```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 git clone ssh://git@git.rublox.pro:2222/rublox/player.git
cd player cd player
npm install npm install
cp .env.example .env cp .env.example .env
# 2. Create a feature branch # 2. Создаём feature-ветку
git checkout -b feature/short-description git checkout -b feature/короткое-описание
# 3. Make changes # 3. Делаем изменения
npm run dev # test locally npm run dev # проверяем локально
npm run lint # check ESLint npm run lint # ESLint
npm run format # apply Prettier npm run format # Prettier
# 4. Commit (Conventional Commits) # 4. Коммитим (Conventional Commits)
git commit -m "feat: add jump animation to GdBall" git commit -m "feat: добавить анимацию прыжка для GdBall"
# Other prefixes: fix:, chore:, docs:, refactor:, test:, perf:, ci: # Другие префиксы: fix:, chore:, docs:, refactor:, test:, perf:, ci:
# 5. Push and open PR # 5. Пушим и открываем PR
git push origin feature/short-description git push origin feature/короткое-описание
# Open PR via https://git.rublox.pro/rublox/player # Открыть 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 - 2-space отступ
- Single quotes (`'foo'`, not `"foo"`) - Одинарные кавычки (`'foo'`, не `"foo"`)
- Semicolons required - Точки с запятой обязательны
- Trailing comma in multi-line literals - Trailing comma в многострочных литералах
- 100-char line width - Ширина строки 100 символов
- No `eval`, no `new Function`, no `innerHTML = ...` - Никаких `eval`, `new Function`, `innerHTML = ...`
- React: hooks rules enforced (`react-hooks/rules-of-hooks`) - React: hooks-правила обязательны (`react-hooks/rules-of-hooks`)
Run before commit: Запускай перед коммитом:
```bash ```bash
npm run format # auto-fixes most things npm run format # авто-фикс большинства
npm run lint # warns about the rest 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 | | `feature/...` | Новые фичи |
| `fix/...` | Bug fixes | | `fix/...` | Багфиксы |
| `chore/...` | Refactoring, deps, tooling | | `chore/...` | Рефакторинг, зависимости, тулинг |
| `docs/...` | Documentation only | | `docs/...` | Только документация |
| `perf/...` | Performance improvements | | `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` - `feat: добавить WaveMode в GdGameModeRegistry`
- `fix: ScriptSandbox crashes on Worker timeout` - `fix: ScriptSandbox падает при таймауте Worker`
- `perf: throttle ui.set() to 250ms with diff check` - `perf: дросселировать ui.set() до 250мс с diff-проверкой`
**Bad:** **Плохо:**
- `update code` - `update code`
- `wip` - `wip`
- `fixed stuff` - `пофиксил всякое`
## PR template ## Шаблон PR
When you open a PR, fill in: При открытии PR заполни:
```markdown ```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 lint` проходит
- [ ] `npm run format:check` passes - [ ] `npm run format:check` проходит
- [ ] `npm run build` succeeds - [ ] `npm run build` собирается
- [ ] Tested locally with `npm run dev` - [ ] Протестил локально через `npm run dev`
- [ ] Updated relevant docs (README / ARCHITECTURE / CHANGELOG) - [ ] Обновил соответствующие доки (README / ARCHITECTURE / CHANGELOG)
- [ ] CLA signed - [ ] CLA подписан
``` ```
## Review process ## Процесс ревью
- The repo maintainer (МИН) reviews every PR. - Мейнтейнер репо (МИН) ревьюит каждый PR.
- Expect feedback within **48 hours** (often same day). - Ожидай фидбек в течение **48 часов** (часто в тот же день).
- Small PRs (<300 lines changed) get reviewed fast. PRs >1000 lines will be asked to split. - Маленькие PR (<300 строк) ревьюятся быстро. PR'ы >1000 строк попросят раздробить.
- After approval, **maintainer merges** (only the maintainer has merge permission). - После approval **мерджит мейнтейнер** (право merge только у него).
- After merge, an automated webhook triggers production deploy. - После merge автоматический webhook запускает деплой в прод.
## What we won't merge ## Что не смерджим
- PRs that add new external dependencies without discussion - PR с новыми внешними зависимостями без обсуждения
- PRs that touch sensitive paths (`engine/scripts/ScriptSandbox*.js`, `engine/multiplayer/*`) without security review - PR трогающие чувствительные пути (`engine/scripts/ScriptSandbox*.js`, `engine/multiplayer/*`) без security-ревью
- PRs that break the build or lint - PR ломающие сборку или линт
- PRs from contributors who haven't signed the CLA - PR от контрибьюторов без подписанного CLA
- Massive refactors without a tracking issue discussed beforehand - Массивные рефакторинги без заранее обсуждённого tracking-issue
## What we love ## Что любим
- Bug fixes with reproducible test cases - Багфиксы с воспроизводимыми тест-кейсами
- Performance improvements with before/after metrics - Улучшения производительности с before/after метриками
- New `engine/gd/Gd*.js` gamemodes - Новые `engine/gd/Gd*.js` гейммоды
- New script API additions (in `ScriptSandboxAPI.js`) - Новые API для скриптов (в `ScriptSandboxAPI.js`)
- Documentation improvements (especially examples) - Улучшения документации (особенно с примерами)
## 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 - Открой issue с лейблом **Question**
- Or hop into the `#разработка` channel at https://team.rublox.pro/chat - Или приходи в канал `#разработка` на 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) [![Лицензия: 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)
[![Commercial license available](https://img.shields.io/badge/Commercial-License--available-green.svg)](./LICENSE-COMMERCIAL.md) [![Коммерческая лицензия](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+ - Node.js 18+ и npm 10+
- A WebGL2-capable browser (Chrome 90+ / Firefox 90+ / Safari 15+) - Браузер с WebGL2 (Chrome 90+ / Firefox 90+ / Safari 15+)
- 4 GB RAM free (Babylon scenes are heavy) - 4 ГБ свободной памяти (Babylon-сцены тяжёлые)
**Install:** **Установка:**
```bash ```bash
git clone ssh://git@git.rublox.pro:2222/rublox/player.git git clone ssh://git@git.rublox.pro:2222/rublox/player.git
cd player cd player
npm install npm install
cp .env.example .env # defaults point at public staging — works out of the box cp .env.example .env # дефолты указывают на публичный staging — работает сразу
npm run dev 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: **Без JWT** ты увидишь экран авторизации. Чтобы обойти его для локальной разработки:
1. Get a 90-day test JWT from a project maintainer (or use your own from rublox.pro). 1. Получи 90-дневный test-JWT у мейнтейнера (или используй свой с rublox.pro).
2. In browser DevTools console: 2. В DevTools браузера:
```js ```js
localStorage.setItem('player_jwt', '<paste-your-jwt-here>'); localStorage.setItem('player_jwt', '<вставь-сюда-свой-jwt>');
location.reload(); 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 ```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 curl -L -o assets.zip https://git.rublox.pro/rublox/player/releases/download/latest/kubikon-assets.zip
unzip assets.zip -d public/ 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 ```bash
echo "VITE_STANDALONE=true" >> .env echo "VITE_STANDALONE=true" >> .env
npm run dev 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/ src/
├── engine/ # Babylon.js engine — 81 files, ~46k lines. ├── engine/ # Движок Babylon.js — 81 файл, ~46k строк.
│ # Self-contained: BabylonScene, GameRuntime, MultiplayerSync, │ # Самодостаточный: BabylonScene, GameRuntime,
│ # PlayerController, BlockManager, DecoManager, ScriptSandbox, │ # MultiplayerSync, PlayerController, BlockManager,
│ # 30+ GD (Geometry Dash) gamemode classes. │ # DecoManager, ScriptSandbox, 30+ классов GD-гейммодов.
├── KubikonPlayer/ # Player container UI: menu, chat, comments, mobile controls. ├── KubikonPlayer/ # UI-контейнер плеера: меню, чат, комменты, моб. контролы.
├── editor-shared/ # HUD components shared with editor: hotbar, healthbar, GUI overlay. ├── editor-shared/ # HUD-компоненты общие с редактором: хотбар, healthbar,
├── AdminPreview/ # Preview routes for designer team (skins / music / portals catalogs). │ # GUI-оверлей.
├── PreviewSkin/ # Routes /_preview-skin/<id> etc. used by team.rublox.pro 3D previews. ├── AdminPreview/ # Превью-роуты для команды дизайнеров (каталоги скинов,
├── components/ # Shared UI: EmailConfirmNotice, KubikonBugReport, Leaderboard. │ # музыки, порталов).
├── api/ # API.js (config) + Kubikon3DService.js (endpoint wrappers). ├── 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. ├── auth/ # PlayerAuth.jsx (JWT/ticket flow), ticketExchange.js.
├── hooks/ # useDeviceType.js (mobile/tablet detection). ├── hooks/ # useDeviceType.js (детект моб./планшет).
├── utils/ # kubikonTime.js (relative time formatting). ├── utils/ # kubikonTime.js (форматирование времени).
├── App.jsx, main.jsx, LoadingScreen.jsx ├── 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_API_BASE` | _(пустая)_ | Базовый URL HTTP-API. Пустой = vite-proxy (для dev). |
| `VITE_REALTIME_HTTP` | `https://dev-api.rublox.pro/api-game` | Colyseus HTTP endpoint (multiplayer matchmaking). | | `VITE_REALTIME_HTTP` | `https://dev-api.rublox.pro/api-game` | Colyseus HTTP-эндпоинт (мультиплеер-матчмейкинг). |
| `VITE_REALTIME_WS` | `wss://dev-api.rublox.pro/api-game` | Colyseus WebSocket endpoint. | | `VITE_REALTIME_WS` | `wss://dev-api.rublox.pro/api-game` | Colyseus WebSocket-эндпоинт. |
| `VITE_RUBLOX_HOME` | `https://rublox.pro/app` | Where to redirect users with no auth. | | `VITE_RUBLOX_HOME` | `https://rublox.pro/app` | Куда редиректить юзеров без авторизации. |
| `VITE_STANDALONE` | `false` | Skip API, load `sample-game.json`. | | `VITE_STANDALONE` | `false` | Пропустить API, загрузить `sample-game.json`. |
| `VITE_API_PROXY_TARGET` | `https://dev-api.rublox.pro` | (dev only) vite-proxy target for `/api-*`. | | `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. 1. Прочитай [CONTRIBUTING.md](./CONTRIBUTING.md) — стиль кода, именование веток, шаблон PR.
2. Sign our [CLA](./CLA.md) — required before any merge (we use a CLA bot in Gitea). 2. Подпиши [CLA](./CLA.md) — обязательно перед первым merge (в Gitea стоит CLA-бот).
3. Open issues for bugs / feature requests via the templates in `.gitea/ISSUE_TEMPLATE/`. 3. Открывай issues для багов/предложений через шаблоны в `.gitea/ISSUE_TEMPLATE/`.
**Quick PR cycle:** **Быстрый цикл PR:**
```bash ```bash
git checkout -b feature/your-feature git checkout -b feature/моя-фича
# ...code... # ...пишешь код...
npm run lint npm run lint
npm run format npm run format
git commit -m "feat: add foo" git commit -m "feat: добавил фичу"
git push origin feature/your-feature git push origin feature/моя-фича
# Open PR at https://git.rublox.pro/rublox/player # Открой PR на https://git.rublox.pro/rublox/player
``` ```
--- ---
## Common tasks ## Команды
```bash ```bash
npm run dev # Start dev server (vite, port 5173) npm run dev # Dev-сервер (vite, порт 5173)
npm run build # Production build → build/ npm run build # Прод-билд → build/
npm run preview # Preview production build locally npm run preview # Превью прод-билда локально
npm run lint # ESLint npm run lint # ESLint
npm run format # Prettier (write) npm run format # Prettier (записать)
npm run format:check # Prettier (check only — used in CI) 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. - **[AGPL-3.0-or-later](./LICENSE)** — для open-source использования. Форки и производные работы (включая сетевые сервисы) обязаны публиковать свой исходник под той же лицензией.
- **[Commercial License](./LICENSE-COMMERCIAL.md)** for proprietary use. Contact `maksimivankov26@yandex.ru`. - **[Коммерческая лицензия](./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 - Главный сайт: https://rublox.pro
- Player demo: https://player.rublox.pro - Демо плеера: https://player.rublox.pro
- Studio (separate repo): https://git.rublox.pro/rublox/studio - Студия (отдельный репо): https://git.rublox.pro/rublox/studio
- Issues & PRs: https://git.rublox.pro/rublox/player - Issues и PR: https://git.rublox.pro/rublox/player
- Security: see [SECURITY.md](./SECURITY.md) - Безопасность: см. [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 1. Описание проблемы
2. Steps to reproduce (or a proof-of-concept) 2. Шаги воспроизведения (или proof-of-concept)
3. Affected versions / files 3. Затронутые версии / файлы
4. Your impact assessment (XSS / RCE / IDOR / sandbox escape / etc.) 4. Твою оценку воздействия (XSS / RCE / IDOR / побег из песочницы / и т.д.)
5. Your contact for follow-up 5. Твой контакт для уточнений
6. Whether you want public credit after the fix (we'll add you to a Hall of Fame in CHANGELOG) 6. Хочешь ли публичное упоминание после фикса (добавим в Hall of Fame в CHANGELOG)
## What to expect ## Что ожидать
| Step | Time | | Шаг | Сроки |
|---|---| |---|---|
| Acknowledgement | within 24 hours | | Подтверждение получения | в течение 24 часов |
| Severity assessment | within 3 business days | | Оценка серьёзности | в течение 3 рабочих дней |
| Fix in private branch | within 7 days for critical | | Фикс в приватной ветке | в течение 7 дней для критичных |
| Public patch release | when ready, with credit | | Публичный релиз патча | когда готов, с благодарностью |
## 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. - **Побег из script-песочницы** (`engine/scripts/ScriptSandbox*.js`) — скрипт юзера получает доступ к `window`, `document`, `fetch`, `localStorage`, либо угоняет сессии других игроков.
- **XSS in game-content rendering** — game titles, chat messages, comment bodies that get rendered as HTML. - **XSS в рендере контента игр** — названия игр, чат-сообщения, тексты комментов рендерятся как HTML.
- **Multiplayer message-injection** — crafted Colyseus messages causing other clients to crash or execute attacker code. - **Инъекция мультиплеер-сообщений** — кастомные Colyseus-сообщения роняют других клиентов или выполняют код атакующего.
- **Auth-token leakage** — JWT or ticket appearing in URLs, query strings, console logs, error pages, or analytics events. - **Утечка auth-токена** — JWT или ticket появляется в URL, query-string, console-логах, error-страницах или analytics-событиях.
- **Asset-URL injection** — `url:...` prefixes (designer-uploaded models) that load arbitrary files from outside our asset bucket. - **Инъекция в 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). - Отсутствующий `X-Frame-Options` или `Content-Security-Policy` (знаем, работаем над этим на стороне сервера).
- Self-XSS (user pasting JS into their own DevTools). - Self-XSS (юзер сам вставляет JS в свой DevTools).
- Outdated `npm audit` warnings without a working exploit. - Устаревшие `npm audit` warning'и без рабочего эксплойта.
- Information disclosure of files in the repo (it's open-source!). - Раскрытие информации о файлах в репо (это же open-source!).
- Reports generated by automated scanners with no manual verification. - Отчёты от автоматических сканеров без ручной проверки.
## 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) - Публичное упоминание в `CHANGELOG.md` (если хочешь)
- Inclusion in a "Hall of Fame" section in this file - Включение в раздел «Hall of Fame» этого файла
- Personal thank-you from the maintainer - Личное спасибо от мейнтейнера
- For high-impact reports: a one-time financial gift at the maintainer's discretion (rare, but possible) - За high-impact-репорты: разовый денежный подарок по усмотрению мейнтейнера (редко, но возможно)
## Hall of Fame ## Hall of Fame
_Empty so far — be the first!_ _Пока пусто — стань первым!_

View File

@ -2,7 +2,7 @@
"name": "rublox-player", "name": "rublox-player",
"version": "1.0.0", "version": "1.0.0",
"type": "module", "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": [ "keywords": [
"rublox", "rublox",
"game-player", "game-player",