studio/rbxl-importer/CHANGELOG.md
min c375ae01ac
All checks were successful
CI / Lint (pull_request) Successful in 1m6s
CI / Build (pull_request) Successful in 2m2s
CI / Secret scan (pull_request) Successful in 26s
CI / PR size check (pull_request) Successful in 7s
CI / Deploy to S1 + S2 (pull_request) Has been skipped
feat(rbxl-import): импорт Roblox .rbxl карт в Rublox-проекты
Тест-фича для МИНа. Полное описание в rbxl-importer/INFO_PROCESS.md.

Backend (rbxl-importer/ на VM 130 S1):
- Python-парсер Roblox Binary (28+ типов значений)
- Asset downloader через Marfusha proxy + .ROBLOSECURITY cookie
- Mesh→GLB конвертер (v1-v5)
- Converter Roblox-классов → project_data
- Flask API: /analyze + /create

Frontend:
- API.js + components/RbxlImportModal.jsx (drag-n-drop)

Тестовый импорт Easy Obby: project_id 2697,
2244 primitives + 742 lua-scripts + 5 ассетов.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 18:24:27 +03:00

8.2 KiB
Raw Blame History

rbxl-importer: лог разработки

2026-06-07

Фаза 0. Подготовка (✓)

  • Освобождено место на S1: удалён pve/data LV (+133 GB), VM 111/112/114/116 (+285 GB). Свободно стало 419 GB в VG pve.
  • Создана VM 130 rbxl-importer (IP 192.168.1.130, Ubuntu 22.04, 4 vCPU, 4 GB RAM, 200 GB).
  • Установлены: Docker, Python 3.11+venv, nginx, postgresql-client.
  • Клонированы studio-rbxl-import и player-rbxl-import worktree, ветка feat/rbxl-import.
  • Smoke-test парсера на Escape Easy Obby Parkour Uncopylocked.rbxl (8205 instances, 120 классов).

Фаза 1. Парсер .rbxl (✓)

  • Реализованы файлы: rbxl_binreader.py, rbxl_types.py, rbxl_parser.py.
  • Декодирование 28+ Roblox PROP типов: String, Bool, Int32, Float, Double, UDim, UDim2, Ray, Faces, Axes, BrickColor, Color3, Vector2, Vector3, CFrame, Quaternion, Enum, Referent, Vector3int16, NumberSequence, ColorSequence, NumberRange, Rect, PhysicalProperties, Color3uint8, Int64, SharedString, Bytecode, OptionalCFrame, UniqueId, Font.
  • Особенности формата покрыты: interleaved-transformed массивы, zigzag для signed int, Roblox float encoding, LZ4 chunks.
  • Протестировано на 6 файлах: 0 warnings:
    • easy_obby.rbxl (Easy Obby Parkour, 437 KB, 8205 instances)
    • miners-haven.rbxl (Miners Haven, 8 MB, 60950 instances)
    • 4 synthetic из rojo-rbx/rbx-dom/benches/files/

Фаза 2. Asset pipeline (✓)

  • БД: миграция 001_roblox_assets.sql (3 таблицы) применена в storys_db (S2 primary через autossh туннель S1 PVE 192.168.1.152:25435).
  • asset_downloader.py: дедупликация по rbx_asset_id + sha256, retry с backoff, классификация по content-type/magic bytes.
  • asset_proxy.py: режимы disabled / direct / http_proxy / cloudflare_worker. Используется http_proxy через Marfusha xray (85.192.61.244:39237).
  • Cookie auth: .ROBLOSECURITY от аккаунта minkorenovsk2 сохранён в /home/min/.roblosecurity на VM 130, EnvironmentFile подключен в systemd unit.
  • mesh_converter.py: парсер Roblox .mesh v1-v5 + GLB writer (glTF 2.0 binary).
    • v1.00 ASCII протестирован: 500 facets, 1500 vertices → 54900 байт GLB.
    • v2-v5 binary — написаны, проверим на реальных файлах.
  • nginx на VM 130: /opt/roblox-assets/ отдаётся как https://assets.rublox.pro/roblox/... с CORS.

Фаза 3. Конвертер геометрии (✓)

  • converter.py: маппинг 30+ Roblox-классов → Rublox project_data.
    • Part, WedgePart, CornerWedgePart, TrussPart → primitives (cube/wedge/cornerwedge).
    • MeshPart, UnionOperation → glbModels (с fallback на bbox cube).
    • SpawnLocation → scene.spawnPoint.
    • Lighting → scene.environment.
    • Sound → scene.sounds.
    • Script/LocalScript/ModuleScript → scene.scripts с kind='roblox-lua' и raw lua_source.
  • Material enum (Plastic→glossy, Neon→neon, Metal→metal, Glass→glass, ...).
  • CFrame → position + Euler XYZ (system axes Roblox = Babylon: right-handed Y-up).
  • Scale: 1 Roblox stud = 0.28 м (настраиваемо).
  • Easy Obby результат: 2244 primitives + 742 lua-scripts + 5 ассетов (sounds) для скачки.

Фаза 4. Lua-runtime + Roblox API shim (✓)

  • wasmoon (Lua 5.4 WASM) интегрирован в player/studio (npm install).
  • RobloxLuaWorker.js — Worker-хост с инициализацией wasmoon, IPC с main thread.
  • RobloxLuaSandbox.js — main-side обёртка.
  • roblox-shim.js — math классы (Vector3, Color3, CFrame, UDim2), Instance прокси (game, workspace, script, GetService, GetChildren, FindFirstChild, IsA с иерархией классов), Part свойства (Position/CFrame/Size/Color/Material/Anchored/CanCollide/Transparency), RBXScriptSignal (Touched, Heartbeat, Stepped, RenderStepped, Connect, Wait, Disconnect).
  • roblox-scheduler.js — корутины через coroutine.create/resume/yield, шедулер для wait/task.wait/task.delay/task.spawn, автоматический fire Heartbeat/Stepped/RenderStepped на каждом tick.
  • roblox-tween.js — TweenService с 10 easing-функциями (Linear, Quad, Cubic, Quart, Quint, Sine, Bounce, Elastic, Back, Exponential) для Vector3/Color3/CFrame/number.
  • roblox-services.js — Players, LocalPlayer, Character, Humanoid (Health, WalkSpeed, JumpPower, TakeDamage, Died), UserInputService, RemoteEvent (FireServer/FireClient/OnServerEvent), RemoteFunction, DataStoreService (GetAsync/SetAsync/IncrementAsync), HttpService (JSONEncode/Decode), ContextActionService stub.
  • roblox-physics.js — BodyVelocity, BodyGyro, BodyPosition, BodyForce, BodyAngularVelocity, AlignPosition, LinearVelocity.

Тесты Lua-runtime: 36/36 ✓

  • tests/rbxl-lua-mvp.test.js — math + Instance + Part + IsA (9/9)
  • tests/rbxl-lua-wait.test.js — корутины + wait/task.wait/task.delay (5/5)
  • tests/rbxl-lua-tween.test.js — TweenService + Linear easing (2/2)
  • tests/rbxl-lua-services.test.js — Humanoid + DataStore + HttpService + RemoteEvent (8/8)
  • tests/rbxl-lua-integration.test.js — реалистичные obby/simulator снейппеты (12/12): KillBrick, WalkSpeed boost, Tween door, BodyVelocity конвейер, leaderstats, DataStore checkpoint, циклы с wait, task.spawn параллель, Color3 + Material смена, RemoteEvent client→server, Heartbeat счётчик, Vector3 arithmetic.

Фаза 5. Flask API + UI (✓)

  • src/app.py Flask:
    • GET /health → ok
    • POST /import/rbxl/analyze → парсер + report + preview_hash (Redis 20 мин TTL)
    • POST /import/rbxl/create → скачка ассетов + конверт mesh→GLB + INSERT в kubikon3d_projects
  • Запущен через systemd unit rbxl-importer.service (Restart=on-failure, EnvironmentFile с cookie).
  • Redis (Docker redis-rbxl) для preview cache.
  • studio/src/components/RbxlImportModal.jsx — React компонент с drag-n-drop, отчётом, формой создания. Доступен только МИНу.
  • studio/src/api/rbxlImporterApi.js — клиент.
  • Тест-результат: Easy Obby импортирован как project_id 2697 (2244 primitives, 742 lua-scripts, 5 ассетов скачано без ошибок).

Фаза 6. Совместимость с плеером + DNS (✓)

  • GameRuntime.js: добавлен _startRobloxLuaScript() метод и ветка if (s.kind === 'roblox-lua') в start().
  • _handleRobloxLuaCommand(): маппит IPC команды от Lua-sandbox (partSet, partVel, playerCmd) на PrimitiveManager и game.player API.
  • _buildRobloxLuaSceneSnap(): преобразует projectData.scene.primitives → формат для Lua (workspace:GetChildren).
  • NPM proxy_host на S1 NPM (VM 101 192.168.1.43): assets.rublox.pro и api-rbxl.rublox.pro → VM 130:80.
  • DNS Cloudflare: 2 A-записи (proxied=false) → 85.175.7.40 (S1 публичный IP).
  • End-to-end протестировано: https://api-rbxl.rublox.pro/health → 200 OK.

Фаза 7. Документация (в работе)

  • README.md в rbxl-importer/
  • INFO_PROCESS.md (этот файл)
  • TODO: commit + PR в Gitea для studio и player worktree.

Известные ограничения

  • Lua-runtime пока MVP: нет GUI (ScreenGui/Frame/TextLabel), нет :Wait() на сигналах через корутины (только Connect), нет Animation/KeyframeSequence.
  • CSG meshes (UnionOperation) парсятся, но конверт в GLB не реализован — bbox cube fallback.
  • Terrain voxel grid конвертится в заглушку (плоский ландшафт).
  • TouchEvent в плеере не fire'ится автоматически из физики Babylon — нужно добавить collision broadcaster.