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>
du -sh натыкался на systemd-private-* в build/wiki/tmp (Permission
denied) → exit 1 → deploy failure, хотя rsync долетел. Теперь verify
проверяет наличие index.html, а du неблокирующий (2>/dev/null||true).
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>
S1 в downtime — деплой не должен валиться, главное доставить на S2.
S1 rsync/verify помечены continue-on-error; S2 остаётся строгим.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI Lint падал: ERR_MODULE_NOT_FOUND eslint-plugin-react-refresh + flat-config
(defineConfig/configs.flat) — это API eslint 9, а в lock eslint 8.57.1.
У студии (lint=success) рабочая схема — legacy .eslintrc.json. Привёл плеер
к ней: удалён eslint.config.js, .eslintrc.json дополнен правилами движка,
lint-скрипт с --ext .js,.jsx.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
REST-fallback чата при ошибке email_not_confirmed попадал в else-ветку и
показывал сырой код email_not_confirmed (англ). WS-путь уже показывал
русскую модалку EmailConfirmNotice. Добавил ту же ветку в REST-catch:
email_not_confirmed → setEmailNotice(true). Игра 2046 не-мультиплеерная,
чат часто идёт REST-фоллбэком → баг был виден именно там.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>