Раньше: проверка дистанции до врага при ЛКМ через InputBegan
+ MouseButton1. Никак не работало из-за десятка причин.
Теперь как в Тире:
- BabylonScene._meshToTarget теперь возвращает {kind:'npc', id:N}
для меша с metadata.npcId.
- routeGlobalEvent('click', {target}) — этим уже шлёт в Lua-shim
с target.
- Shim добавлен __rbxl_npc_on_click(ref, fn) — регистрация callback'а.
В fireGlobalEvent при type='click'+target.kind='npc' резолвим
локальный ref и фейерим cb.
- В скрипте игры 20 регистрируем callback на каждого врага.
Клик ЛКМ по NPC (raycast попадает в мешa NPC) → callback → урон.
В 3-м лице курсор свободный. _handlePlayClick ВСЕГДА пикал центром
экрана через _pickFromCenter — независимо от того где находится курсор.
Поэтому клик мышкой по мишени не срабатывал — пик шёл из центра.
Фикс: проверяем document.pointerLockElement:
- locked (1-е лицо) → _pickFromCenter (прицел всегда в центре)
- !locked (3-е лицо) → scene.pick(clickX, clickY) по реальной позиции
курсора при клике.
Убрал debug-логи.
Раньше при смене языка код оставался как есть → подсветка кричит
ошибками, юзер пишет JS в Lua-режиме и наоборот.
Сейчас:
- Скрипт хранит code_js и code_lua отдельно (плюс активный code).
- При переключении JS↔Lua: текущий code сохраняется в слот ТЕКУЩЕГО
языка, достаётся слот ЦЕЛЕВОГО языка. Если слот пустой — шаблон.
- При обычном save (печатает юзер) код зеркалится в слот активного
языка чтобы не потерять при swap.
- Никаких модалок: переключение мгновенное, ничего не пропадает.
Сценарии:
- Новый проект: js-шаблон в code_js. Клик Lua → подставляется lua-шаблон,
code_js сохранён.
- Юзер написал JS-код, переключился на Lua: JS улетел в code_js,
показывается пустой Lua-шаблон. Клик обратно JS → код возвращается.
- Старые проекты (без code_js/code_lua): первое переключение
засеет слот текущего языка из code.
Слайдеры sun/hemi/ambient/exposure/contrast/saturation теперь
сохраняются в projectData.scene.lighting при save и применяются
обратно при load.
Раньше параметры жили только в текущей сессии — после refresh
страницы возвращались к дефолтам.
Импортированные .rbxl карты также сохраняют выставленные пользователем
параметры света.
В Свет и атмосфера добавлено:
- Заливка теней (scene.ambientColor) — позволяет окрасить тени в
сером тоне без пересвета diffuse материалов.
- Экспозиция (ipc.exposure 0.3-2) — общая яркость через
imageProcessingConfiguration.
- Контраст (ipc.contrast 0.5-2)
- Насыщенность (colorCurves.globalSaturation -100..+100)
Юзер крутит слайдеры до момента когда импортированная Roblox-карта
выглядит как оригинал. Дефолты: ambient 0.3, exposure 1.0, contrast
1.0, saturation 1.0.
Также убрал mat.ambientColor=цвет — теперь default (0,0,0). Освещение
управляется глобально через панель.
Состояние пока не сохраняется в проект (только сессия). Persistence
добавим в следующем шаге.
Vector3:
- Magnitude теперь getter (без скобок) — как в Roblox
- Unit теперь getter
- Поддержаны lowercase алиасы magnitude, unit
Сохранение:
- BabylonScene serialize включает language в scripts[]
- Clip/copy включает language
- LuaSharedWorker.handleInit обёрнут в try/catch с детальной ошибкой
- LuaSharedWorker использует статический import для wasmoon
Этап 2 завершён полностью. Lua-runtime прошёл все тесты:
print, warn, Vector3, Color3, UDim2, CFrame, Enum, task.delay/spawn/defer,
RunService.Heartbeat, math/string/table, pcall.
Следующий этап 3: DataModel (game.Workspace + Instance + script.Parent +
Part.Touched + Part.Position setter).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Этап 1 (UI):
- Скрипт имеет поле language: 'js' | 'lua' (дефолт 'js')
- Переключатель JS / Lua в шапке ScriptEditor (жёлтый / синий)
- При смене с пустого/template — подставляется шаблон нового языка
- При смене с реальным кодом — confirm
- Monaco автоматически переключает подсветку
- Badge JS/LUA в HierarchyPanel рядом с именем скрипта
Этап 2 (базовый runtime):
- LuaSharedSandbox — обёртка с API совместимым с ScriptSandbox
- LuaSharedWorker — Web Worker с одним wasmoon-VM на всю игру
- RobloxShim — Vector3/Color3/UDim2/Vector2/CFrame, Enum.*, print/warn,
wait/task.*, RbxSignal, Instance.new (база), game.GetService (стабы),
RunService.Heartbeat
- Scheduler для task.delay/defer через main loop tick
- GameRuntime разделяет скрипты: JS / Roblox-Lua (импорт) / user-Lua
На Этапе 3 — DataModel (game.Workspace + Instance.Parent + Touched).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1) Стартовый экран загрузки больше НЕ показывается в студии при тестовом
запуске (scene._editorMode), только в плеере на rublox.pro «Играть».
2) Новая игра: коллаб-сессия поднимается сразу после первого сохранения
(без перезагрузки) + кнопка «Пригласить» авто-сохраняет проект.
3) Незалогиненный по collab-ссылке → форма входа rublox.pro/login (origin без
/app, был 404) с ?return → возврат на инвайт-ссылку.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LoadingScreenOverlay: Ken-Burns фон (CSS pan+zoom) + 4 стиля (ken-burns/static/
parallax/particles) + карточка-композиция (cover/название места/автор/verified-SVG).
Стартовый экран при входе в Play (showStartupLoadingScreen из enterPlayMode +
поля проекта loadingScreen.* + serialize/deserialize). API game.loading.
setBackground/isVisible/onHide + расширенный show. UI редактора: секция
«Стартовый экран входа (Ken Burns)». Вики g5 #62 + статья. Тест-игра 2713.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
game.fx.autoMobFloaters(true) — включает облачка урона над NPC при любой потере
HP (NpcManager.damage). NpcManager.damageByMesh — оружие (бластер/меч) наносит
урон скриптовым NPC (weapons.setOnHit → npcManager.damageByMesh). Связка:
выстрел бластера → урон NPC → авто-floater «-N» над целью.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
FloaterManager.js: object pool (30 billboard-планов с DynamicTexture), tween
подъём+fade+покачивание, crit pop-scale, цвета damage/crit/heal/mana/miss,
стек одинаковых по stackKey (×N), комикс-стиль (BAM!/KAPOW!/POW! на звезде).
API game.fx.damageFloater(position, value, opts) — position {x,y,z} или ref/
'player'. Интеграция: tick в render-loop, resetRuntime при stop. Тест-игра
«Тренировочный полигон» id=2676.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
onKeyDown клал любую клавишу в _codes (набор для WASD-движения камеры),
включая D при зажатом Ctrl → камера летела вправо при копировании. Теперь
клавиши с ctrl/meta в _codes не попадают.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
duplicateSelected для model/userModel/primitive ставил копию на sel.x+1 →
визуальное смещение. Теперь копия появляется в той же точке (как Roblox Studio).
Block остаётся с поиском свободной клетки (воксель нельзя в занятую).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GameRuntime.saveProgress/loadProgress — helper к storys savegame endpoint
(/kubikon3d/savegame/<pid>/<uid>/<ns>) для движковых менеджеров.
- Достижения: при unlock сохраняются в БД (namespace _achievements) + localStorage
как быстрый кэш; loadFromDB при Play восстанавливает разблокированные.
- Лидерстаты: статы текущего игрока сохраняются в БД (namespace _leaderstats,
дебаунс 1с при set); loadFromDB при Play восстанавливает значения.
- Загрузка из БД через 250мс после старта скриптов (даём define зарегистрировать).
Теперь прогресс игрока подгружается при каждой сессии с любого устройства.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Leaderstats: HUD-таблица top-right (blur, сортировка по primary, топ-10,
подсветка me, flash-инкремент). API game.leaderstats.define/set/add/get/
onChange + me.* (format number/time/short). LeaderstatsManager.js.
Достижения: toast справа (4 редкости + звук + очередь, slide-in/out), кнопка-
кубок слева-снизу → страница grid (locked grayscale+замок, hidden=?, прогресс-
бар). API game.achievements.define/unlock/has/bindToStat/setButtonVisible/
openPage. bindToStat(id, stat, {gte/lte/eq}) — авто-unlock по лидерстату.
Сохранение unlocked в localStorage по проекту. AchievementsManager.js.
Интеграция: оба менеджера в BabylonScene (tick leaderstats в Play, resetRuntime
при stop, serialize/load в project_data scene.leaderstats/achievements). worker-
API + GameRuntime cmd-обработчики + мост leaderstats.onChange→worker (globalEvent
leaderstatsChange) для bindToStat. Плеер пока НЕ портирован (по плану).
Тест-игра «Сбор монет с достижениями» id=2616 (is_test): поляна + 30 монет +
3 стата + 5 достижений (3 через bindToStat).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) Враг с HP → R15-NPC (зомби-скин), преследует и бьёт игрока при касании.
2) Волна врагов: враги наносят урон при касании (onTick дистанция → damage).
3) Удалённые скрипты больше не исполняются: _cleanupOrphanScripts при удалении
объекта (primitive/model/userModel) + перед enterPlayMode чистим скрипты-сироты.
4) Ключ и замок: ключ из примитивов (стержень+кольцо-torus+бородка), дверь
как дверь-по-E (плавный поворот вокруг петли, только с ключом).
6) Тени-полосы: normalBias 0.005→0.02 (убирает acne-полосы от соседних объектов).
Машина (vehicle:car) — остаётся рантайм-спавном (особенность транспорта).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) Дверь по коду: открытую можно закрыть по E (onInteract) → снова вводить код.
2) NPC: процедурная анимация ходьбы (покачивание по Y + наклон корпуса) для
Kenney-моделей — раньше скользили без анимации.
3) Торговец переделан в NPC-персонажа (spawnNpc character-a) + невидимый
триггер с диалогом по E (вместо примитивов).
4) Тени: убрана «полоса через всю карту» — autoCalcDepthBounds off,
shadowMaxZ 90/60 (было 200/120), lambda 0.6, frustumEdgeFalloff 12.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) При выделении папки (клик по сцене / вставка кита) дерево авто-раскрывается:
workspace + цепочка родителей + scrollIntoView к строке папки. Раньше папка
выделялась на сцене, но в свёрнутом дереве её не было видно.
2) Delete на выделенной папке (type='folder') → removeFolder(id, true) удаляет
всю папку со ВСЕМ содержимым + _cleanupOrphanScripts чистит осиротевшие
скрипты привязанные к удалённым объектам.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) Предметы кита из тулбокса спавнятся на ТВЁРДОЙ поверхности под центром
экрана (getPlacementPointAtCenter: raycast в пол/объект), а не под камерой.
2) Многочастный кит (дверь) теперь реально попадает в папку: insertGameplayKit
ставил folderId, но дерево не пересобиралось (markDirty не трогает
hierarchyDirtyRef) — добавлен hierarchyDirtyRef.current=true.
3) enterPlayMode снимает любое выделение редактора (объект/папка) + убирает
пивот папки и gizmo — в Play больше нет подсветки выбранного.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) Длинная тень-полоса: csm.frustumEdgeFalloff=8 — тень персонажа больше не
тянется на весь пол.
2) Удаление примитива/модели/блока через ПКМ теперь обновляет дерево
(markDirty + hierarchyDirtyRef) — раньше объект удалялся, но не пропадал.
3) Клик по СЦЕНЕ по объекту в папке → выделяется ВСЯ папка (selectByMesh
проверяет folderId). Отдельную часть — через раскрытие папки в дереве.
4) Free-drag папки: зажал ЛКМ на группе и тянешь — двигается вся папка
(moveFolderBy по дельте центра).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Дельта пивота применялась только в dragEnd → объекты телепортировались в
конце. Теперь _onFolderGizmoDrag применяет инкрементальную дельту на каждом
тике (setOnDrag) — движение/вращение/масштаб группы видно в процессе, как
у одиночных объектов.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Клик по папке в дереве → выделяется вся группа (подсветка всех объектов
внутри, рекурсивно по подпапкам) + групповой gizmo на пивоте в центре папки.
Манипуляторы двигают/вращают/масштабируют ВСЕ объекты папки сразу. Выбор
отдельной модели внутри — манипулирует только ей (как раньше).
- FolderManager: getFolderObjects (рекурсивный сбор + центр), moveFolderBy,
scaleFolder (от центра, +размеры примитивов), rotateFolderY расширен на модели.
- SelectionManager.selectFolder → multi-подсветка + type:'folder' + пивот-gizmo.
- BabylonScene._attachFolderGizmo/_applyFolderGizmo: пивот-TransformNode,
на dragEnd дельта (move/rotate/scale) применяется ко всей папке, пивот
пересоздаётся в новом центре. Пивот убирается при смене выделения.
- Дерево: клик по строке папки = выделить группу; клик по шеврону = свернуть.
Многокомпонентные модели уже кладутся в авто-папку (ModelManager) — теперь
их можно двигать как единое целое.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Киты «Сундук» и «Счётчик монет» связаны через game.broadcast('coins',{add})
+ game.onMessage('coins') — раньше каждый кит в своём worker, счётчик не
обновлялся (был globalThis, не работает между воркерами).
- Точку спавна теперь МОЖНО удалить: Delete (SelectionManager.deleteSelected
обрабатывает type==='spawn' → scene.deleteSpawn) + ПКМ в дереве → контекст-
меню «Навести камеру / Удалить точку спавна».
- Если точка спавна удалена (_spawnEnabled=false) — игрок появляется в
(0, поверхность+2, 0). Постановка новой точки (setSpawnAtCamera) возвращает.
- spawnEnabled сериализуется в project_data.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- game.self.rotate(ry)/rotateY(ry) добавлен в worker (слал scene.rotate с
ref объекта-носителя). Кит «Вращающийся объект» падал 'game.self.rotate is
not a function' каждый кадр в onTick — теперь крутится.
- upsertScript принимает name; вставка кита даёт скрипту имя = название кита
(раньше в дереве был сырой id script_mq03...). Ручное создание скрипта тоже
даёт «Скрипт N» / «Скрипт объекта N» вместо id.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- F в редакторе теперь фокусирует камеру на ВЫДЕЛЕННОМ объекте (раньше всегда
летел в центр 0,0,0). Если выделения нет — центр сцены. Только в edit-режиме.
- focusOnSelection поддерживает userModel + запасной путь по позиции меша.
- Вставка кита из Тулбокса: объект выделяется И камера наводится на него
(видно, куда добавилось) + переключение на инструмент «Выделить».
- Кит «Двойной прыжок» чинён: был setJumpPower (высокий прыжок) →
game.player.setDoubleJump(true) (настоящий второй прыжок в воздухе по Space).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Environment больше НЕ рисует свою жёлтую сферу-солнце/луну/фон (флаг
_drawSkyBodies=false) — иначе на небе было два солнца. Единое небо рисует
SkyboxManager (купол + солнечный диск + облака + горы). SkyboxManager стал
единым источником освещения: каждый пресет выставляет direction/intensity/
color солнца и ambient (lights переданы в конструктор), fadeTo плавно ведёт
и свет. Environment оставлен только для day/night cycle совместимости.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Процедурный gradient-skybox без внешних текстур: купол-сфера с ShaderMaterial
(градиент верх→горизонт→низ + солнечный диск + дымка), low-poly горы на
горизонте, billboard-облака с дрейфом, атмосферный туман, звёзды.
Пресеты: clear-summer-day / lowpoly-roblox / cloudy / sunset / starry-night /
space. Плавный fadeTo между пресетами (анимация цветов купола в tick).
game-API (студия): game.scene.setSkybox/setClouds/setFog,
game.scene.skybox.fadeTo/setSunDirection. Сериализация неба в project_data.
Тик облаков/перехода работает и в редакторе (превью).
Плеер пока НЕ портирован (по указанию — сначала проверка в студии).
Тест-игра «Небесная демка» id=2541 (dev-режим is_test=true, не в ленте).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Дерево «Объекты сцены»: авто-раскрытие ветки + скролл к объекту при
выборе на сцене (HierarchyPanel useEffect на selection).
- Копирование/дублирование примитива сохраняет вращение rotationX/Y/Z
(SelectionManager клал selection без rotation → копия теряла поворот).
- Копирование/дублирование переносит скрипты объекта на копию
(_copyScriptsToNewObject + clip.scripts для Ctrl+C/V).
- userModels (воксельные модели) теперь видны в дереве в группе «Мои
модели», можно выбрать/удалить/прикрепить скрипт (target kind userModel
уже поддержан в GameRuntime).
- Free-drag: перетаскивание объекта ЛКМ как в Roblox Studio — скольжение
по полу/поверх объектов с AABB-коллизией (скольжение вдоль преграды).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
Живое 3D-меню как в топ-играх Roblox: cinematic-камера облетает витрину,
патч-ноуты, логотип, кнопка ИГРАТЬ, музыка, блок управления.
- game.mainMenu.show/hide/setCamera/setPatchNotes/onShow/onPlay/onHide
- 4 режима камеры: cinematic(waypoints)/orbit/static/preset-cuts поверх camera.cutscene
- зацикливание облёта через onCutsceneDone (камера не вылетает за сцену)
- game.player.setInputBlocked экспортирован в worker + handler в runtime
- passthrough scene.mainMenu в toJSON/load
- вики g5 #60 guide-garage, тест-игра «Гараж Босса» id 2434 (GLB-машина Kenney)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Движок: PlacementManager (тень-превью формой воксельной модели за курсором,
снап к сетке, стопка, проверка зоны и баланса, поворот R/колесо, ПКМ/Esc),
ShopInventoryUi (магазин-слоты, авто-серые при нехватке валюты); проводка
game.placement.* и game.inventoryUi.* в worker/GameRuntime/BabylonScene.
Попутные фиксы:
- TerrainManager: backFaceCulling=false — воксели не просвечивают (видна была
задняя грань сквозь переднюю);
- KubikonEditor: guard от потери userModels/scripts при частичной загрузке
(terrain догрузился, модели/скрипт нет → автосейв затирал) — критичный
фикс защиты данных для ВСЕХ игр;
- Hotbar: пустой инвентарь не показывает панель (глобальное правило);
- MinimapOverlay: миникарта только по флагу игры (не авто на больших картах);
- cleanup usermodel-инстансов при Stop.
Вики: карточка #58 + статья-урок «Мой завод» (g5 Разбор готовых игр),
openProjectId=2345, скриншоты залиты на прод.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
При scale-гизмо mesh.scaling тянул faceUV → studs превращались в полосы.
Фикс: во время drag прячем studs-текстуру (плоский цвет), в dragEnd меш
пересоздаётся с правильным faceUV. _recreateMesh для studs пересоздаёт
материал заново (свежий тайлинг + восстановление текстуры).
GizmoController: + onDrag (live) колбэк для scale.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Текстура studs v4: круглые кружки с усиленным объёмом (normal strength 4.0,
запечённый блик/тень) + контактная тень от каждого кружка. Фон 0.97 — цвет
остаётся сочным. emissive 45% от цвета на примитивах (Roblox-look).
- Версионные имена файлов (studs_v4_*) — обход browser-кэша Babylon.
- Color-пикер блоков: в палитре при выборе окрашиваемого блока (studs-block)
под категориями появляется ряд из 8 лего-цветов + input «свой цвет».
BabylonScene.setActiveBlockColor → addBlock(...,color) при постановке.
- DEV-хук ?dev=<имя> (localhost): грузит /dev-<имя>.json в редактор для
локального теста без БД (на проде неактивен).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Баг: стрелка-указатель game.fx.pointer не переключалась на следующую цель —
при касании цель не менялась, стрелка не выключалась.
Первопричина (две движковые проблемы):
1. findOne(x).onTouch(...) не существовал: Instance-proxy не имел методов
касания, движок ловил touch только объектов со скриптом-target/триггеров.
2. Race: скрипт исполняется синхронно в init, а sceneSnapshot приходил позже
(rAF) → findOne() на старте = null → подписки onTouch молча не вешались.
Фикс:
- Instance-proxy: + onTouch/onUntouch/onClick → шлёт inst.watchTouch{ref}.
Worker: _instTouchHandlers + маршрут instTouch/instUntouch/instClick по ref.
- GameRuntime: handler inst.watchTouch/watchClick → _watchedTouchRefs;
routeInstEvent(ref,type); сброс в teardown.
- BabylonScene._detectTouchEvents: блок watched-объектов (AABB по ref, rising/
falling edge → routeInstEvent), _refToTarget(ref)→{kind,id},
_touchState.clear() в enterPlayMode.
- Первичный snapshot сцены передаётся прямо в init
(ScriptSandbox.setInitialScene → worker заполняет _sceneIndex до userFn) →
findOne работает в синхронном теле скрипта на старте.
Проверено: телепорт игрока по 3 целям игры 333 — стрелка переключается
red-cube→blue-sphere→gold-chest, на финале удаляется.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Задача 01 из 1 - Неделя 4/ЗАДАЧИ РУБЛОКС. P0-приоритет: без таблиц
с кнопками невозможны симуляторы, тайкуны, фермы.
Новое:
- engine/BillboardUiManager.js — 4 пресета (shop-item, shop-purchase,
banner, sign), 18 иконок, DynamicTexture-рендер, UV-hit-test
- PrimitiveTypes: новый тип 'billboard' в категории 'gameplay'
- PrimitiveManager: case billboard в _createMeshForType (Plane), init
через applyToMesh, billboardOpts в updateInstance
- BabylonScene: PointerEventTypes-handler для кликов с _isPlaying-чеком
и pointer-lock поддержкой
- GameRuntime: команды billboard.set/update/onClick, callback через
sandbox.sendEvent('billboardClick')
- ScriptSandboxWorker: пространство game.billboard.{set,update,onClick}
- BillboardEditorModal.jsx — модалка с живым canvas-превью, 8 готовых
градиентов + кастомные пикеры, дропдаун из 18 иконок
- InspectorPanel: кнопка 'Редактировать табличку…' для billboard-примитива
- KubikonEditor: проброс модалки через onEditBillboard prop
- Icon.jsx: SVG prim-billboard
Два режима ориентации: 'camera' (BillboardGui-аналог, всегда смотрит
на игрока) и 'fixed' (SurfaceGui-аналог, прикреплён к поверхности).
Клик-детекция через ray-pick → UV → пиксели текстуры → поиск кнопки
по AABB; работает с пиксельной точностью даже при повороте камеры.
Документация: RUBLOX_STUDIO_FUNCTIONS.md раздел 1.25.
Тестовая игра 'Магазин апгрейдов' (4 таблички + банер + HUD) — МИН
соберёт в студии drag-n-drop'ом.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
BabylonScene.onKeyDown глобально перехватывал Space (preventDefault для
прокрутки страницы при WASD-навигации камеры). isTypingTarget проверял
только input/textarea/contentEditable — но Monaco роутит keydown через
свой внутренний div, и e.target оказывается не textarea, а
.monaco-editor-container div.
Фикс: добавлена проверка target.closest('.monaco-editor') — если фокус
в Monaco, считаем что юзер печатает и не глотаем клавиши.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Большой консолидирующий коммит после поднятия 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>