studio/src/editor/engine/README.md
МИН 61fba4e174
Some checks failed
CI / Lint + Format (push) Failing after 32s
CI / Build (push) Failing after 37s
CI / Secret scan (push) Failing after 37s
CI / PR size check (push) Has been skipped
fix: починка билда + studio.rublox.pro инфра
Большой консолидирующий коммит после поднятия studio.rublox.pro (28 мая 2026).
Содержит изменения которые делались в процессе подготовки прод-окружения:

Фиксы импортов после выноса из minecraftia:
- Массовая замена путей ../../components → ../components (40+ файлов в src/community/, src/admin-preview/)
- Замена ../KubikonEditor/ → ../editor/, ../KubikonStudio/ → ../community/, ../AdminPreview/ → ../admin-preview/
- API.js скопирован из минки целиком (было 8 экспортов, стало 312)
- Добавлены PLAYER_URL, MyButton_1, недостающие компоненты
- Заменены require() на статические ES-imports в BabylonScene, PrimitiveManager, GameRuntime (Vite не поддерживает CJS require)

Структура ассетов:
- public/kubikon-templates/ → public/assets/kubikon-templates/
- public/kubikon-learn/ → public/assets/kubikon-learn/
- (код искал в /assets/, файлы лежали без /assets/)

Навигация роутов внутри студии:
- /kubikon-studio/docs → /docs (90+ навигационных вызовов sed-replaced)
- /kubikon-editor/X → /edit/X, /kubikon/play/X → /play/X, /kubikon/gd/X → /gd/X

UI:
- Новый компонент StudioHeader (61px, как в минке) + копия favicon
- WithHeader wrapper в App.jsx для всех страниц кроме fullscreen-редактора/плеера
- SSO ticket-flow в AuthContext (auto-redeem #ticket= при загрузке)
- Тёмная тема карточек игр в ВИКИ (фон #1c2231 вместо #fff, картинка впритык)

Документация:
- docs/ONBOARDING.md — путь нового контрибьютора от нуля до PR
- docs/TUTORIAL_ADD_SCRIPT_API.md — как добавить game.* API
- API_USAGE.md — список эндпоинтов backend
- README в подпапках engine/, engine/terrain/, engine/voxel/, engine/robloxterrain/, engine/types/

.gitignore:
- public/wiki/ исключён (73МБ PNG, будут на CDN отдельной задачей)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 05:01:13 +03:00

159 lines
11 KiB
Markdown
Raw 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.

# Движок студии Рублокс
Это сердце [studio.rublox.pro](https://studio.rublox.pro). Тут живёт всё: рендер Babylon-сцены, физика, скрипты пользователей, мультиплеер, ландшафт, ассет-менеджмент.
Для контрибьютора, который впервые видит этот код — читай этот README сверху вниз, дальше доки по подпапкам.
## 1. Слои движка
Снизу вверх:
```
┌─────────────────────────────────────────────────────┐
│ React UI (panels, тулбары) │
├─────────────────────────────────────────────────────┤
│ GameRuntime ← оркестратор «игрового │
│ PlayerController режима» (когда игрок │
│ ScriptSandbox(Worker) жмёт Play в редакторе) │
├─────────────────────────────────────────────────────┤
│ Менеджеры объектов сцены │
│ BlockManager — блоки 1×1×1 │
│ PrimitiveManager — сферы/цилиндры/конусы │
│ ModelManager — GLB-модели из библиотеки │
│ UserModelManager — модели юзера (CAD-редактор) │
│ NpcManager — NPC и враги │
│ DecoManager — трава/цветы/деревья │
├─────────────────────────────────────────────────────┤
│ Системы поверх сцены │
│ PhysicsWorld — AABB + интеграция Хейуна │
│ SelectionManager — клик → подсветка │
│ GizmoController — translate/rotate/scale gizmos │
│ HistoryManager — Ctrl+Z / Ctrl+Y │
│ MultiplayerSync — Colyseus state-sync │
├─────────────────────────────────────────────────────┤
│ Низ: BabylonScene = Engine + Scene + Camera │
│ TerrainManager + voxel/ │
└─────────────────────────────────────────────────────┘
```
`BabylonScene.js` — точка входа. Создаёт `Engine`, `Scene`, `UniversalCamera` с Roblox-style контролами (ПКМ + WASD-полёт), подключает всех менеджеров.
## 2. Как игрок ставит блок (полный путь)
Это самый частый кейс. Понимаешь его → понимаешь как работают все остальные менеджеры.
```
1. User жмёт ЛКМ в редакторе
2. BabylonScene.onCanvasPointerDown
- делает ray из камеры через курсор
- scene.pickWithRay() → выясняет, в какую грань какого меша попали
3. Если активен инструмент «Кисть блоков»:
BlockManager.placeBlock(pos, blockType)
- вычисляет grid-aligned позицию (округление к 1×1×1)
- создаёт InstancedMesh от шаблонного меша блока (один draw call на тип)
- регистрирует в внутренней карте: pos.x|y|z → mesh
- HistoryManager.push({ action: 'place', pos, type })
4. Если активен Multiplayer:
MultiplayerSync.sendBlockPlaced({ pos, type })
- летит в Colyseus-комнату
- сервер броадкастит остальным игрокам
- у них BlockManager.placeBlock() вызывается снова, но без HistoryManager.push
```
## 3. Менеджеры — зачем их столько
Каждый менеджер владеет одной категорией объектов. Менеджеры **не знают друг о друге** — все общаются через `BabylonScene` (он же `scene`-объект, проброшен в каждый менеджер при init).
| Менеджер | Что хранит | Ключевой метод |
|---|---|---|
| **BlockManager** | блоки grid-aligned | `placeBlock(pos, type)` / `removeBlock(pos)` |
| **PrimitiveManager** | сферы/цилиндры/конусы любого размера | `addPrimitive({ type, pos, size, color })` |
| **ModelManager** | GLB-модели (мечи, деревья, машины) | `addModel({ modelId, pos, rotation, scaling })` |
| **UserModelManager** | модели созданные юзером в встроенном CAD | `addUserModel({ userModelId, pos })` |
| **NpcManager** | NPC и враги (zombies — отдельный `ZombieManager`) | `spawnNpc({ type, pos })` |
| **DecoManager** | мелкие воксельные декорации (трава 0.05м) | `paintDeco(pos, brushSize, model)` |
| **TerrainManager** | гладкий ландшафт (legacy, voxel-режим) | `paintVoxel(pos, material)` |
| **VoxelWorld** + **VoxelRenderer** | новый chunks-based воксельный движок | `setVoxel(x,y,z, type)` |
| **FolderManager** | дерево объектов (как Workspace в Roblox) | `createFolder(name, parentId)` |
| **GuiManager** | UI игры (HUD, меню) | `setUiElement(id, props)` |
| **InventoryManager** | инвентарь игрока (хотбар, рюкзак) | `addItem(itemId, count)` |
| **WeaponSystem** | оружие, выстрелы, перезарядка | `equip(weaponId)` / `fire()` |
| **ScriptSandbox** | JS-скрипты пользователей (см. §5) | `runScript(scriptCode, gameApi)` |
## 4. Подпапки
- **[terrain/](./terrain/)** — legacy воксельный ландшафт (TerrainManager). Кисти, материалы, plant-кисти. Соединён с `BabylonScene` через `TerrainManager.js` в корне.
- **[voxel/](./voxel/)** — новый chunks-based движок (16×16×16 чанки + greedy meshing). См. [RUBLOX_VOXEL_ENGINE_PLAN.md](../../../../RUBLOX_VOXEL_ENGINE_PLAN.md). Пока работает параллельно с legacy TerrainManager как shadow-копия для замеров.
- **[robloxterrain/](./robloxterrain/)** — Roblox-style визуальные эффекты для гладкого ландшафта (vertex AO, slope-darken, distance fog).
- **[types/](./types/)** — общие type-определения и enum'ы (BlockTypes, PrimitiveTypes).
## 5. Скрипты пользователей (sandbox)
`ScriptSandbox.js` + `ScriptSandboxWorker.js` — самая опасная часть движка. Тут юзеры пишут JS, который запускается в их браузере при игре.
Каждый скрипт запускается **в отдельном Worker** (изоляция: нет доступа к DOM, window, fetch). Общение со сценой — только через `postMessage` и проксированное API `game.*`:
```js
// что доступно скрипту:
game.player.damage(10)
game.player.kill()
game.scene.spawn('zombie', { x: 0, y: 0, z: 5 })
game.ui.set('score', 42)
game.broadcast('event', payload) // другим скриптам
game.onMessage(handler)
game.onTick(handler) // ~60 раз/сек
```
Полный список API: [reference_kubikon_scripting_api.md](../../../../disaster-recovery/) (приватный, не публикуется в opensource).
**Не звать `game.ui.set` в `onTick` без throttle!** React setState на 60Hz убивает FPS. Дросселировать через 250мс. [feedback_kubikon_ui_set_throttle].
## 6. Что НЕ трогать (опасные оптимизации)
После пары инцидентов задокументировано:
- **`scene.blockMaterialDirtyMechanism = true`** — ломает рендер новых мешей (трейсеры пуль, debris). Babylon не пересчитывает uniforms для новых материалов.
- **`scene.createOrUpdateSelectionOctree()`** в hot path — O(N²) каждый кадр, лагает на 1000+ мешей.
- **`scene.render()` вручную** — Babylon сам в RequestAnimationFrame, дублирование = double render.
- **`setInterval(..., 16)`** для игровой логики — используй `scene.onBeforeRenderObservable.add(fn)`, тогда привязано к рендер-циклу.
Подробнее в [docs/TUTORIAL_DEBUG_BABYLON.md](../../../docs/TUTORIAL_DEBUG_BABYLON.md).
## 7. Game Runtime — особый режим
`GameRuntime.js` — когда юзер жмёт «Play» в редакторе. Это не отдельный код-путь, а **набор флагов** на тех же менеджерах:
- `PlayerController.spawn()` — создаёт игрового персонажа (R15-скелет) на spawn-блоке
- `PhysicsWorld.enable()` — включается AABB-симуляция (в редакторе отключена)
- `ScriptSandbox.startAll()` — запускает все скрипты пользователей
- `MultiplayerSync.join()` — если игра опубликована, коннектится к Colyseus-комнате
Когда юзер жмёт «Stop» — всё откатывается, состояние из HistoryManager восстанавливается.
## 8. Производительность — ориентиры
| Объект | Сколько ок | Сколько начинает лагать |
|---|---|---|
| Блоки (InstancedMesh) | 50 000 | 200 000+ |
| Примитивы (StandardMesh) | 500 | 2000+ |
| GLB-модели | 200 | 500+ (зависит от вершин) |
| NPC | 50 | 100+ (физика дорогая) |
| Активных скриптов | 30 | 100+ (каждый = Worker = поток) |
| Частицы | 5000 | 20 000+ |
FPS-цель: **60 FPS на средних ноутбуках 2020+**, **30 FPS на школьных машинках 2015+**.
## 9. Что почитать дальше
- [terrain/README.md](./terrain/README.md) — воксельный ландшафт
- [voxel/README.md](./voxel/README.md) — новый chunks-движок
- [../README.md](../README.md) — про папку editor/ выше
- [docs/TUTORIAL_ADD_BLOCK.md](../../../docs/TUTORIAL_ADD_BLOCK.md) — добавить новый тип блока
- [docs/TUTORIAL_DEBUG_BABYLON.md](../../../docs/TUTORIAL_DEBUG_BABYLON.md) — отладка Babylon-сцены
- [docs/TUTORIAL_ADD_SCRIPT_API.md](../../../docs/TUTORIAL_ADD_SCRIPT_API.md) — добавить API в `game.*`
Вопросы — в канал `#разработка` на https://team.rublox.pro.