# Архитектура студии Рублокса

Как редактор превращает действия мыши в воксельный мир, 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)). Это нужно чтобы проект мог продавать коммерческие лицензии корпорациям.
