docs: переписал README/ARCHITECTURE/CONTRIBUTING/SECURITY/CHANGELOG на русский
Юзер указал что вся документация opensource-репо должна быть на русском. Также: - .env.example комменты на русском - package.json description на русском - Описания org и repo в Gitea обновлены через API
This commit is contained in:
parent
87444ee2c8
commit
8428cda555
34
.env.example
34
.env.example
@ -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
|
||||
|
||||
138
ARCHITECTURE.md
138
ARCHITECTURE.md
@ -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)). Это нужно чтобы проект мог продавать коммерческие лицензии корпорациям.
|
||||
|
||||
38
CHANGELOG.md
38
CHANGELOG.md
@ -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`.
|
||||
|
||||
180
CONTRIBUTING.md
180
CONTRIBUTING.md
@ -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
158
README.md
@ -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)
|
||||
[](./LICENSE-COMMERCIAL.md)
|
||||
[](./LICENSE)
|
||||
[](./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)
|
||||
|
||||
82
SECURITY.md
82
SECURITY.md
@ -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!_
|
||||
_Пока пусто — стань первым!_
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user