Что:
- _resolveModelSource:
* Mixamo (skin_y-bot/x-bot/eve/...) → /character-assets/skins/<id>.glb
(с rublox-site, non-humanoid-rigged kind)
* Legacy R15 (skin_bacon-hair, skin_sigma-labubu и др.) — сохранена
старая ветка через manifest + /kubikon-assets/. Это нужно пока
бэк storys работает в legacy-режиме (RUBLOX_NEW_SKINS_AVAILABLE != true).
- skinFolderRef.current default: skin_bacon-hair → skin_y-bot
- BabylonScene._playerModelType default + миграция character-* → skin_y-bot
- PlayerController._modelTypeId default → skin_y-bot
- MultiplayerSync: все дефолты → skin_y-bot
LOCAL DEV:
- На localhost плеер сначала пробует localStorage('rublox_selected_skin')
(тот же ключ что в rublox-site), потом БД. Это позволяет тестить выбор
скина в сайте без записи в прод-БД.
Зависит от:
- PR storys (новый бэк-резолв + feature-flag)
- PR user (endpoint /<id>/gender)
- Заливки 80 GLB на rublox.pro/character-assets/skins/ (отдельная инфра-задача)
Из merge остались два блока объявлений задачи 20 → 'Identifier _lsMirror already declared' в Web Worker → ВСЕ игры запускались без скриптов. Убрал переобъявление во втором блоке.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GraphicsManager (постобработка/материалы/API game.graphics) — паритет со студией,
применяется при загрузке игры если автор настроил. Новые материалы chrome/water/
iridescent. Realtime-эндпоинт переведён на game.rublox.pro (S1 NPM прямо, без
hop через S2 — чинит разрывы WebSocket). MultiplayerSync улучшен.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Порт LoadingScreenOverlay (Ken-Burns/4 стиля/карточка/verified) + старт-экран
при входе в Play + API game.loading.setBackground/isVisible/onHide. Идентично
студии. worker SOURCE синтаксис проверен. Проверено headless в плеере (0 ошибок).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
show() игнорировал колбэки из опций — onPlay из mainMenu.show({onPlay}) не
регистрировался, кнопка ИГРАТЬ ничего не делала. Теперь опции-колбэки пушатся
в _onPlay/_onShow/_onHide.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ReferenceError: require is not defined при game.self.setLabel/scene.setLabel
в плеере. Заменён require('./LabelManager') на статический import (как в студии).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LeaderstatsManager + AchievementsManager скопированы в плеер, интегрированы
в BabylonScene/worker/GameRuntime (те же точки, что в студии): HUD-таблица,
toast, кубок+страница, bindToStat, сохранение прогресса в БД (savegame, JWT),
мост onChange→worker. Прогон 2616 в плеере: таблица в DOM, 0 ошибок. Полная
фича-парность задачи 20.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
self.rotate(ry)/rotateY шлёт scene.rotate с ref носителя (обработчик
scene.rotate в плеере уже был). Иначе вращающиеся объекты падали бы в плеере.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Фича-парность: Environment не рисует жёлтую сферу/луну (флаг _drawSkyBodies),
SkyboxManager — единый источник неба и света (lights в конструкторе). Порт
правок студии 1:1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Фича-парность со студией: namespace game.mainMenu (show/hide/setCamera/
setPatchNotes/колбэки) + зацикливание облёта через onCutsceneDone +
game.player.setInputBlocked в worker + handler в runtime + passthrough
scene.mainMenu в load. Проверено: меню работает в плеере на игре 2434.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Фича-парность со студией: LoadingScreenOverlay.js (DOM-оверлей),
namespace game.loading в worker (хэндл local→real + колбэки через
globalEvent), cmd loading.* + _ensureLoadingScreen в GameRuntime,
class-ref + tick + load конфига в BabylonScene. Проверено: экран
загрузки работает в плеере на тест-игре «Такси-босс» 2427.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Скрипт «Мой завод» (id 2345) падал в плеере на game.format.money —
неймспейс был только в worker студии. Из-за краха в синхронной части
не доходило до inventoryUi.create/placement → инвентарь не показывался.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PlacementManager + ShopInventoryUi + проводка game.placement.*/inventoryUi.*
в worker/GameRuntime/BabylonScene — опубликованные tycoon-игры с расстановкой
теперь работают в плеере. + TerrainManager backFaceCulling=false (воксели не
просвечивают), cleanup usermodel при Stop, Hotbar скрыт при пустом инвентаре.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
faceUV для куба (кружки одного размера на всех гранях) + studDensity
(плотность кружков) — портировано из студии.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Два бага меню в плеере:
1. Повторный ESC открывал меню ПОВЕРХ первого (не закрывал).
2. После открытия/закрытия меню переставала работать orbit-камера по
зажатой ПКМ (игры задачи 2 camera_mouse_controls).
Первопричина: ESC слушали ДВА обработчика — движок (setOnExitRequest →
_onEscMenu) и React (отдельный keydown при topMenuOpen). На одно нажатие
срабатывали оба → гонка: меню дублировалось, а _uiCursorMode застревал в
true, из-за чего onCanvasMouseDownGlobal (if _uiCursorMode return) игнорировал
ПКМ → orbit-камера не включалась.
Фикс — единый источник истины в движке:
- BabylonScene: флаг _playerMenuOpen + toggle в setOnExitRequest (открыто→
закрыть+setUiCursorMode(false), закрыто→открыть). _onEscMenu(open) передаёт
состояние в UI. setPlayerMenuOpen(open) — синхронизация при закрытии из UI
(кнопка «Продолжить»). Сброс флага в enterPlayMode.
- KubikonPlayer: setOnEscMenu((open)=>setTopMenuOpen(open)); УБРАН дублирующий
React ESC-обработчик; onClose меню → setPlayerMenuOpen(false); синхронизация
_playerMenuOpen=true в onLockChange (perma) и setOnPlayChange.
- PlayerController.setUiCursorMode(true): сброс _rmbHeld=false (иначе если меню
открыли при зажатой ПКМ, флаг застревал → orbit «думал» что ПКМ активна).
Проверено: ESC открыл→ESC закрыл (1 меню в DOM), ПКМ-orbit работает после меню.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Портирование фикса из studio (фича-парность движков). Баг: стрелка-указатель
game.fx.pointer не переключалась на следующую цель.
- find/findOne/all раньше возвращали голую строку-ref → .onTouch невозможен.
Приведены к студийному Instance-proxy (_getOrCreateInstance, coerces в строку
через Symbol.toPrimitive → обратно совместимо со старым кодом).
- Instance-proxy: + onTouch/onUntouch/onClick → inst.watchTouch{ref}.
Worker: _instTouchHandlers + маршрут instTouch/instUntouch/instClick;
_detectSnapshotDeltas для changed/destroying-событий.
- GameRuntime: inst.watchTouch/watchClick → _watchedTouchRefs; routeInstEvent.
- BabylonScene._detectTouchEvents: блок watched-объектов + _refToTarget;
_touchState.clear() в enterPlayMode.
- Первичный snapshot сцены в init (setInitialScene) → findOne на старте.
Проверено на проде player.rublox.pro/333: стрелка переключается
red-cube→blue-sphere→gold-chest, на финале удаляется.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Привёл _setupInput/onPointerLockChange к рабочей студийной реализации:
- onCanvasMouseDownGlobal/onWindowMouseUpGlobal — ПКМ-orbit с проверкой
needPermLock() (как в студии), вместо самодельных onRmbDown/onRmbUp.
- onPointerLockChange: при потере lock выход из Play (меню) ТОЛЬКО если
needPermLock (first/lockfirst/sideview/shiftLock). В third потеря lock =
отпустили ПКМ → остаёмся в Play. Это убирает рандомное открытие меню.
- onCanvasClick лочит только в perma-режимах.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>