KubikonEditor подмешивал skin_folder из БД в hash без проверки.
Для ~22 legacy-юзеров БД отдаёт skin_bacon-hair (модель удалена) →
в Play-режиме студии играл бекон. Теперь невалидный скин (не в
MIXAMO_SKINS и не customskin:) подменяется на skin_y-bot, как в
плеере (KubikonPlayer/GameMenu) и кабинете. Дефолты bacon → y-bot.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After backend CORS rollout users had stale CORS-failure cached for
Mixamo GLB. Adding a query suffix forces browsers to re-fetch the URL
instead of replaying the cached failure.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Синхронизация с rublox-player (Этап 1 ANIMATIONS_PLAN.md):
MIXAMO:
- Добавлен MixamoAnimator.js (полная копия из плеера)
- В PlayerController список MIXAMO_SKINS (78 шт)
- _resolveModelSource ветка для skin_* — грузит GLB с /character-assets/skins/
- _loadPlayerModel создаёт MixamoAnimator для Mixamo-скинов
CROUCH (Ctrl):
- AABB → 0.45, скорость 0.45×walk, приоритет над sprint
- Анимации: crouch_enter → crouch_idle / crouch_walk → crouch_to_stand
- Y-drop по 0.20-0.45м для разных Mixamo-клипов
- Анти-флик debounce + детект one-shot vs loopable
PREVIEW PLAYER:
- Skin приоритет: URL #skin= → БД → localStorage → дефолт
- Дефолт skin_bacon-hair → skin_y-bot
ENTERPLAYMODE:
- BabylonScene при Play читает hash/localStorage и подставляет user skin
поверх projectModelType (тест-режим = играешь СВОИМ скином)
KUBIKONEDITOR:
- handlePlay async: предзагрузка скина из БД (если нет в URL) и инжект в hash
- При Play: requestFullscreen() — блокирует Ctrl+W/D/T/R/S/A/P/F и др.
- Во время Play: window keydown listener блокирует системные хоткеи,
WASD проходят к PlayerController (для crouch+движение)
GraphicsManager: постобработка (bloom/FXAA/виньетка/цветокор/DoF) + тени/SSAO,
10 пресетов, mobile-safe, выкл по умолчанию. Новые материалы примитивов
(chrome/water/iridescent + улучшены glass/neon). API game.graphics.*. Графика +
Стартовый экран (Ken Burns) + Экран загрузки вынесены из Настроек в новый
GameDecorModal, открываются из вкладки «Игра» (группа «Оформление»). Вики-раздел
«Графика и эффекты» (GR1-GR4) + AI-контекст обновлён.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Дополнил коллаб-синхрон: GUI-элементы (guiManager create/update/remove),
папки (folderManager createFolder/renameFolder/removeFolder, id выравнивается
у соавторов через Map), пользовательские модели (userModelManager addInstance
с forceInstanceId / removeInstance). Списки в Hierarchy обновляются штатным
setInterval. Теперь синхронятся: примитивы, модели, блоки, скрипты, GUI,
папки, userModels.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Раньше синхронизировались только примитивы/модели/блоки, а скрипты нет —
у соавтора было 0 скриптов. Перехватываем scene.upsertScript/removeScript,
шлём op scriptUpsert/scriptRemove; applyRemoteOp применяет их у соавтора
(список в Hierarchy обновляется штатным setInterval). Лимит соавторов 5
(MAX_COLLABORATORS в realtime StudioRoom, задеплоен на VM110).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ITERATION 6 (single-VM rewrite):
- RobloxLuaSharedWorker: один wasmoon-state на 742 скрипта (не 742 VM)
- Pre-populated Workspace + Player.PlayerGui перед addScripts
- На каждом Part — Touched/TouchEnded сигналы; на каждом TextButton —
MouseButton1Click/Activated/MouseEnter/Leave; Humanoid с Died/Health
- Двухфазный init: addScriptsBatch ВСЕ скрипты → kickoff() с PlayerAdded
- wait()/task.wait/task.spawn/task.delay через scheduler+coroutines
- guiClick от Rublox-GUI → fireEvent → инстанс.MouseButton1Click.Fire()
- playerTouch → part.Touched.Fire(HumanoidRootPart) + humanoid.Touched
ITERATION 7 (nullStub compatibility):
- debug.setmetatable(nil, ...) + debug.setmetatable(function() end, ...)
с полным набором __index/__newindex/__call/__add/__sub/.../__len/__concat
- Возврат undefined из FindFirstChild/WaitForChild (вместо JS proxy)
- Lua-side __null_stub_singleton с Connect/connect/Wait/Fire (lowercase aliases)
- __rbxl_lookup_part через __rbxl_parts_by_id table (не ipairs на JS array)
- script.Parent гарантированно не nil (либо реальный Part либо null stub)
- RbxSignal: Connect+connect, Wait+wait, Fire+fire, Disconnect+disconnect
- SIGNAL_NAMES whitelist расширен: Tool (Selected/Equipped), Remote (OnInvoke),
ChatMakeSystemMessage, etc.
Converter:
- GUI: UDim2 dataclass правильно резолвится (scale*100 + offset/viewport*100)
- размеры в процентах (как Rublox-GuiOverlay ожидает)
- ScreenGui.Enabled → пропагируется в детей
- Эвристика скрыть HD Admin/Chat/CommandBar/TeleportTo модалки
- rbxasset:// rbxassetid:// фильтруются на пустой URL
Hierarchy:
- scroll-to-selected раскрывает workspace+rootPrims+folders перед scroll
- data-sel-id на всех ItemRow с rAF×2 timing
Известные ограничения:
- Synapse X obfuscated скрипты часто всё равно падают (требуют конкретный Roblox-VM)
- но debug.setmetatable перехват не даёт скриптам валиться на indexing/arithmetic
- реальные пользовательские KillBrick (Touched) теперь работают
- GUI кнопки → MouseButton1Click работают
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>
- UDim2: scale теперь умножается на viewport reference (1280×720),
раньше игнорировался — фреймы получали 0×0 и фейлились на дефолт 100×30
или наоборот заполняли всё окно
- _udim2_pair(): пара (x,y) через _udim2_to_rublox(axis='x'|'y')
- Фильтр rbxasset:// rbxassetid:// rbxhttp:// rbxthumb:// URL'ов на пустую
строку — браузер их не загружает, спам в console исчезает
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Все 5 задач итерации:
1. Single-VM mode (RobloxLuaSharedWorker/Sandbox):
- один Worker, одна wasmoon-VM на ВСЕ скрипты проекта
- addScript() для каждого, общий tick/event broadcast
- снимает WASM OOM (1 VM 16MB вместо 742 × 16MB)
- убран per-script лимит 50, теперь все 742 загружаются
2. Touched events:
- sendGlobalEvent в shared sandbox распознаёт playerTouch
и пересылает в Worker как 'touched' с primId
- Worker находит Part по __primId в workspace и Fire'ит
его Touched сигнал — Lua-обработчики работают
3. Click в иерархии → scroll-to-selected:
- useEffect в HierarchyPanel ловит изменение selection
и scrollIntoView для нужного ItemRow
- data-sel-id атрибут на primitive/model/block строках
4. GUI Roblox в конвертере:
- ScreenGui/Frame/TextLabel/TextButton/ImageLabel/TextBox →
scene.gui c полным набором свойств (UDim2→pixel, Color3→hex,
BackgroundTransparency→bgOpacity, parentId)
5. Чистка:
- удалены debug-console.warn из PlayerController._loadPlayerModel
(убирает spam '[PlayerController.devlog]' в consoles)
Co-Authored-By: Claude Opus 4.7 <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>
_applySelfDelete удалял меш, но запись в _interactables оставалась → промпт
«E Собрать» висел на месте собранного предмета. Теперь запись чистится по ref.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) add() заполняет сначала hotbar, потом grid → собранные предметы сразу видны
в постоянном хотбаре (раньше уходили в скрытую сетку — хотбар казался пустым).
2) Хотбар поднят bottom 14→64px, не перекрывает подсказку внизу экрана.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
При свободном курсоре (нет pointer-lock, 3-е лицо) выстрел шёл из getForwardRay
(фокус камеры). Теперь onDown берёт координаты клика → setAimScreenPoint → луч
через точку клика; onMove обновляет _holdAim для авто-огня при удержании. При
pointer-lock (1-е лицо, курсор в центре) — прежнее поведение (центр).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Меши NPC ставились isPickable=false → raycast бластера/меча проходил сквозь
них, урон и авто-floater не срабатывали. Теперь меши NPC pickable + npcId в
metadata; damageByMesh находит NPC по metadata (быстро) или по rootMesh.
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>
Новый кит (категория ui): определяет лидерборд (Очки primary + Время),
время идёт само, очки растут от broadcast('score'|'coins'). Сохраняется в БД.
Работает вместе со счётчиком монет/очков. Всего 47 китов.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
loadProgress/saveProgress (лидерстаты/достижения) слали fetch без Authorization
→ 401 UNAUTHORIZED. Используют _economyAuthHeaders() (JWT игрока из localStorage).
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>
skybox.clouds.color='#fff' → substring(4,6)='' → parseInt NaN → addColorStop
'rgba(255,15,NaN,0.9)' падал при load → прерывал загрузку проекта. hexToRgb
теперь расширяет #fff→#ffffff и подстраховывает NaN.
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+2) Враг с HP / волна врагов: радиус удара 3.5 (NPC останавливался на
followGap=2.5, урон-чек d<2.5 не срабатывал). Добавлена анимация атаки —
R15Animator.attack (выпад рукой), npc.setAttacking, NpcManager.setAttacking.
3) Ключ исчезает при подборе: scene.setVisible теперь парсит ref ('primitive:N')
— obj.visible=false слал {ref} без kind/id, поэтому ключ не пропадал.
4) Машина — остаётся рантайм vehicle:car (особенность транспорта).
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 закрыть» теперь только когда дверь открыта
и игрок рядом (через onKey+onTick, без постоянного interact-промпта).
2) NPC-киты используют R15-скин 'skin_roblox-noob' → процедурная анимация
бега/покоя с руками и ногами (R15Animator), вместо безжизненного покачивания.
3) Торговец-кит: невидимый триггер (insertGameplayKit теперь уважает
prim.visible=false, раньше хардкод visible:true) + NPC-персонаж рядом —
синий куб больше не виден.
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) NPC-преследователь/торговец/волна: spawnNpc('robot') → 'character-a'
(модели 'robot' не существует в ModelTypes → spawnNpc возвращал null → ошибка).
2) Дверь по коду: верный код → ПЛАВНОЕ открытие вокруг петли (как дверь по E),
декор-панели вращаются вместе с полотном. Раньше полотно уезжало вниз,
декор оставался.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) Дверь по коду: красивая составная дверь (полотно+рамка+кодовая панель),
поле ввода появляется ТОЛЬКО когда игрок в радиусе 6м (onTick по дистанции).
2) game.self.setLabel/clearLabel добавлены (кит «Метка с именем» падал
'setLabel is not a function').
3) Плитка «Готовые механики» в тулбоксе считает киты динамически
(GAMEPLAY_KITS.length), а не хардкод «12».
4) Консоль: ошибки/логи скриптов привязаны к источнику — справа строки
кликабельная ссылка «📄 имя скрипта», открывает скрипт в редакторе
(_log прокидывает scriptId/scriptName).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) scene.setColor теперь принимает {ref} (obj.color=hex), не только {id}.
Светофор переключал цвета через obj.color, но ref игнорировался → не работал.
2) Грядка: добавлен obj.scale (scene.setScale → mesh.scaling). Урожай после
сбора исчезает, растёт за 5с (scale 0→1) и зреет цветом красный→зелёный,
при полном размере снова собирается.
3) Кит «HP-бар» теперь сам прячет стандартный HUD HP (setHpVisible false).
Новый кит «Скрыть стандартный HUD HP» — отдельно прячет дефолтную полосу.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Корень: serialize примитивов/моделей/userModel НЕ сохранял folderId. При
Play→Stop сцена восстанавливалась из снапшота без группировки → все части
кита (светофор/шипы/дверь) вываливались из папки в общие «Примитивы».
Добавлен folderId в serialize всех 3 менеджеров + восстановление в loadFromArray
(model/userModel явно, primitive через opts.folderId).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Зона опасности / триггеры (canCollide:false) ловились camera-clamp, и камера
прыгала к игроку внутри зоны. Причина: metadata примитива НЕ содержал
canCollide, а PlayerController._clampCameraToWorld проверяет md.canCollide.
Добавлен canCollide в metadata меша (+ синк при updateInstance).
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>
Добавлены все оставшиеся механики из TOOLBOX_KITS_FROM_WIKI.md:
Мир: зона опасности, шипы, светофор, грядка-урожай, падающие предметы.
Интерфейс: счётчик очков, HP-бар, дверь по коду (textbox), метка с именем,
обратный отсчёт, 3D-стрелка-указатель.
Эффекты: костёр (particles fire), магнит монет.
NPC и бой (новая категория): преследователь, торговец (modal.dialog),
мишень, враг с HP, волна врагов, диалог/кат-сцена, машина (vehicle:car).
Экономика (новая категория): магазин-кнопка, кликер, ключ+замок.
+2 категории китов (NPC и бой, Экономика). Всего ~37 китов.
Опущены «Главное меню» и «Экран загрузки» — требуют целой сцены, не «1 клик».
Все 45 скриптов прошли синтаксис-проверку, билд зелёный.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ручка/филёнки уезжали на обратную сторону двери: формула поворота смещения
была правосторонняя, а Babylon mesh.rotation.y — левосторонняя. Единая rotY()
(wx=lx·c+lz·s, wz=-lx·s+lz·c) для полотна И декора → всё открывается синхронно
в одну сторону.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>