studio/ARCHITECTURE.md
МИН 31adbf151b Initial public release: Студия Рублокса v1.0
Open-source веб-студия для создания игр Рублокса, двойная лицензия
AGPL-3.0 + Коммерческая.

Главное:
- Vite 5 + React 18 + Babylon 7.54.3 + Monaco Editor + Colyseus 0.16
- Самодостаточный движок ~28к строк (66 файлов): BlockManager,
  TerrainVoxelBuilder, ModelManager, DecoManager, PlayerController,
  ScriptSandboxWorker, MultiplayerSync, 30+ GD-гейммодов
- Главный редактор KubikonEditor (~37к строк) + панели, ScriptEditor (Monaco)
- Витрина игр (KubikonFeed, KubikonStudio, KubikonDocs, KubikonLearn)
- Geometry Dash sub-app (GdMenu, GdShop, GdRules, GdCoverArt)
- 10 admin-preview каталогов для дизайнеров (скины, музыка, порталы и т.д.)
- Конфигурируемый бэкенд через VITE_API_BASE — работает со staging
  (dev-api.rublox.pro) без настройки
- Standalone-режим (VITE_STANDALONE=true) — открыть пустой редактор без бэка
- Полная документация (на русском): README, ARCHITECTURE, CONTRIBUTING,
  SECURITY, CHANGELOG
- ESLint + Prettier + EditorConfig
- Legal: LICENSE (AGPL-3.0), LICENSE-COMMERCIAL.md, CLA.md, COPYRIGHT.md
- Issue templates: bug_report, feature_request, security_disclosure

Перед публикацией:
- Все импорты из minecraftia заменены на локальные
- Все хардкоды URL (minecraftia-school.ru) и внутренних IP убраны → env
- Admin-эндпоинты Kubikon3DService вырезаны (остаются в приватном репо)
- AdminKubikonModeration не публикуется (модерация — в team.rublox.pro)
- 93 МБ ассетов public/kubikon-assets вынесены в .gitignore
  (раздаются через release artifact)
2026-05-27 23:41:10 +03:00

166 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Архитектура студии Рублокса
Как редактор превращает действия мыши в воксельный мир, GLB-модели, скрипты на JS — и сохраняет в JSON для запуска в плеере. Чтение ~10 минут.
## Общий поток (открытие проекта)
```
URL = /edit/<gameId>
AuthProvider читает JWT из localStorage
KubikonEditor.jsx (~3500 строк) главный контейнер, useParams().id = projectId
├── GET /api-storys/kubikon3d/projects/{id} → project_data (JSON)
BabylonScene.create() создание Babylon engine, scene, lights, skybox
GameRuntime.loadProject() парсит project_data, спавнит:
│ - BlockManager.placeBlock() × N (воксели)
│ - ModelManager.spawnModel() × N (GLB Kenney)
│ - DecoManager.placeDeco() × N (трава, камни)
│ - PrimitiveManager.add() × N (box/sphere/cylinder)
│ - PlayerController.spawn() (камера-«редактор»)
ОСНОВНОЙ UI на сцене:
│ - TopRibbon (тулбар)
│ - HierarchyPanel (дерево объектов слева)
│ - InspectorPanel (свойства справа)
│ - TerrainPanel (кисти ландшафта)
│ - ScriptEditor (Monaco)
│ - ToolboxModal (выбор моделей)
│ - GuiOverlay/Hotbar (HUD режима игры)
ЦИКЛ РЕДАКТИРОВАНИЯ юзер:
- кликает мышью → SelectionManager
- drag-and-drop → GizmoManager
- переключает кисти → TerrainManager
- пишет скрипт → ScriptEditor + Babylon-эмулятор
- жмёт «Сохранить» → POST /kubikon3d/projects/:id
- жмёт «Тест» → embedded preview-player
```
## Главные модули редактора
### `editor/KubikonEditor.jsx` (3452 строки)
Корневой компонент. Хранит ссылки на scene, engine, runtime, managers. Обрабатывает горячие клавиши, undo/redo через `HistoryManager`. Обвязывает все панели вокруг `<canvas>`.
### `editor/engine/` (66 файлов, ~28к строк)
Самодостаточный Babylon-движок. Точно такой же как в плеере, но с дополнительными редакторскими функциями:
| Менеджер | Файл | Что делает |
|---|---|---|
| `BabylonScene` | `BabylonScene.js` | Wrapper над Engine+Scene, освещение |
| `GameRuntime` | `GameRuntime.js` | Оркестратор: loadProject/start/pause/dispose |
| `PlayerController` | `PlayerController.js` | R15-персонаж, камеры FPV/TPV, контролы |
| `BlockManager` | `BlockManager.js` | Воксельные блоки uint16-сетка |
| `TerrainVoxelBuilder` | `terrain/*` | Greedy meshing для чанков |
| `ModelManager` | `ModelManager.js` | Загрузка GLB через AssetContainer + кеш |
| `DecoManager` | `DecoManager.js` | ThinInstances для тысяч пропсов |
| `PrimitiveManager` | `PrimitiveManager.js` | Box/sphere/cylinder примитивы |
| `SelectionManager` | `SelectionManager.js` | Клик → выделение → highlight |
| `GizmoManager` | `GizmoManager.js` | Стрелки перемещения/вращения/масштаба |
| `HistoryManager` | `HistoryManager.js` | Undo/redo стек |
| `ScriptSandbox` | `scripts/ScriptSandbox.js` | Запуск user JS в Web Worker |
| `MultiplayerSync` | `multiplayer/MultiplayerSync.js` | Colyseus 0.16 клиент |
| `Audio/Weapon/Zombie/Npc/Dynamics` | `*Manager.js` | Игровые менеджеры |
### `editor/engine/scripts/ScriptSandbox*.js`
Безопасный JS-runtime для пользовательских скриптов. Запускается в Web Worker, без доступа к window/document/fetch. Через postMessage-мост даёт API:
```js
game.onTick((dt) => { ... });
game.onKey('space', () => { player.jump(); });
scene.findOne('Cube1').rotateY(0.1);
ui.set({ score: 42 });
```
### `editor/engine/types/`
TypeScript-определения для Monaco-автокомплита. Когда юзер пишет скрипт — IDE показывает все доступные методы.
## UI-панели
```
+----------------------------------------------------------+
| TopRibbon: Файл | Правка | Тест | Опубликовать | Помощь |
+--------+-----------------------------------+-------------+
| Hierar | | Inspector |
| chyPan | | Panel |
| el | <canvas WebGL> | (свойства |
| | | выделен- |
| Дерево | | ного) |
| объек- | | |
| тов | | |
| | | |
| +-----------------------------------+ |
| | Hotbar / TerrainPanel (внизу) |
+--------+-------------------------------------------------+
```
## Скриптовый редактор (Monaco)
`editor/ScriptEditor.jsx` запускает Monaco (~5МБ vendor chunk, lazy-loaded). Подгружает .d.ts из `engine/types/` для автокомплита. При сохранении скрипт идёт в `ScriptSandbox`, который запускает Worker и шлёт результат обратно.
## Поток данных при сохранении
```
Save кнопка → собрать снимок:
- blocks[] (uint16 array → RLE-compress → base64)
- models[] {id, type, x, y, z, rx, ry, rz}
- primitives[] {id, type, color, size}
- deco[] {type, instances[]}
- script.code (текст из Monaco)
- settings {sky, fog, multiplayer, isGd}
- spawnPoint {x, y, z}
→ JSON.stringify
→ PUT /api-storys/kubikon3d/projects/<id> { project_data: "<json>" }
```
## Чего НЕТ в студии
- **Само воспроизведение игры в проде** — это [Плеер](https://git.rublox.pro/rublox/player) (отдельный домен `player.rublox.pro`). В студии есть `preview-player/` для теста «прямо здесь».
- **Лента / поиск опубликованных игр** — на главном сайте `rublox.pro/app`.
- **Админка модерации** — в `team.rublox.pro/moderator/*` (приватный фронт команды).
## С чего начать новую фичу
| Что хочешь добавить | Начни здесь |
|---|---|
| Новый тип блока | `editor/engine/CONST/blockTypes.js` |
| Новая декор-фабрика | `admin-preview/gd<тип>/` (фабрика) + регистрация в DecoManager |
| Новое API скриптов | `editor/engine/scripts/ScriptSandboxAPI.js` + .d.ts в `engine/types/` |
| Новая GD-механика | `editor/engine/Gd<тип>.js` + регистрация в `GdGameModeRegistry.js` |
| Новый UI-блок инспектора | `editor/InspectorPanel.jsx` |
| Новая кисть ландшафта | `editor/TerrainPanel.jsx` + `TerrainManager.brush*` |
## Производительность
Главные узкие места (что смотреть первым делом):
1. **`game.ui.set()` каждый кадр** — React setState 60Hz убивает FPS. Дросселируй 250мс + diff.
2. **`scene.findOne()` на старте скрипта** — sceneSnapshot приходит через rAF. Звать в `onTick` или setTimeout(0).
3. **`blockMaterialDirtyMechanism=true`** в Babylon — НЕ включать (ломает рендер новых мешей).
4. **GLB через `SceneLoader` вместо `AssetContainer`** — течёт материалами.
5. **Monaco-instance создаётся повторно при ремаунте** — закешируй ссылку.
6. **Воксельный rebuild на каждый блок** — батчить через requestIdleCallback.
## Связь со студией / плеером / минкой
- **Бэкенд один на всех** — `api-storys` микросервис (см. `disaster-recovery/` в приватном репо мейнтейнера).
- **Авторизация общая** — JWT с rublox.pro и player.rublox.pro работают здесь.
- **API-контракт описан в `api/Kubikon3DService.js`** — все эндпоинты `/kubikon3d/*`.
## Лицензионные заметки для контрибьюторов
Контрибьютя, ты соглашаешься лицензировать свои изменения под AGPL-3.0 И предоставляешь мейнтейнеру неисключительную безотзывную лицензию на сублицензирование (см. [CLA.md](./CLA.md)). Это нужно чтобы проект мог продавать коммерческие лицензии корпорациям.