Большой консолидирующий коммит после поднятия 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>
Движок студии Рублокс
Это сердце 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/ — legacy воксельный ландшафт (TerrainManager). Кисти, материалы, plant-кисти. Соединён с
BabylonSceneчерезTerrainManager.jsв корне. - voxel/ — новый chunks-based движок (16×16×16 чанки + greedy meshing). См. RUBLOX_VOXEL_ENGINE_PLAN.md. Пока работает параллельно с legacy TerrainManager как shadow-копия для замеров.
- robloxterrain/ — Roblox-style визуальные эффекты для гладкого ландшафта (vertex AO, slope-darken, distance fog).
- types/ — общие type-определения и enum'ы (BlockTypes, PrimitiveTypes).
5. Скрипты пользователей (sandbox)
ScriptSandbox.js + ScriptSandboxWorker.js — самая опасная часть движка. Тут юзеры пишут JS, который запускается в их браузере при игре.
Каждый скрипт запускается в отдельном Worker (изоляция: нет доступа к DOM, window, fetch). Общение со сценой — только через postMessage и проксированное API game.*:
// что доступно скрипту:
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 (приватный, не публикуется в 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.
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 — воксельный ландшафт
- voxel/README.md — новый chunks-движок
- ../README.md — про папку editor/ выше
- docs/TUTORIAL_ADD_BLOCK.md — добавить новый тип блока
- docs/TUTORIAL_DEBUG_BABYLON.md — отладка Babylon-сцены
- docs/TUTORIAL_ADD_SCRIPT_API.md — добавить API в
game.*
Вопросы — в канал #разработка на https://team.rublox.pro.