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)
9.7 KiB
Архитектура студии Рублокса
Как редактор превращает действия мыши в воксельный мир, 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:
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>" }
Чего НЕТ в студии
- Само воспроизведение игры в проде — это Плеер (отдельный домен
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* |
Производительность
Главные узкие места (что смотреть первым делом):
game.ui.set()каждый кадр — React setState 60Hz убивает FPS. Дросселируй 250мс + diff.scene.findOne()на старте скрипта — sceneSnapshot приходит через rAF. Звать вonTickили setTimeout(0).blockMaterialDirtyMechanism=trueв Babylon — НЕ включать (ломает рендер новых мешей).- GLB через
SceneLoaderвместоAssetContainer— течёт материалами. - Monaco-instance создаётся повторно при ремаунте — закешируй ссылку.
- Воксельный rebuild на каждый блок — батчить через requestIdleCallback.
Связь со студией / плеером / минкой
- Бэкенд один на всех —
api-storysмикросервис (см.disaster-recovery/в приватном репо мейнтейнера). - Авторизация общая — JWT с rublox.pro и player.rublox.pro работают здесь.
- API-контракт описан в
api/Kubikon3DService.js— все эндпоинты/kubikon3d/*.
Лицензионные заметки для контрибьюторов
Контрибьютя, ты соглашаешься лицензировать свои изменения под AGPL-3.0 И предоставляешь мейнтейнеру неисключительную безотзывную лицензию на сублицензирование (см. CLA.md). Это нужно чтобы проект мог продавать коммерческие лицензии корпорациям.