studio/rbxl-importer
min 9caea93d32
All checks were successful
CI / Lint (pull_request) Successful in 1m6s
CI / Build (pull_request) Successful in 1m58s
CI / Secret scan (pull_request) Successful in 23s
CI / PR size check (pull_request) Successful in 7s
CI / Deploy to S1 + S2 (pull_request) Has been skipped
feat(rbxl-import): single-VM Lua runtime + GUI tree + Touched/click events
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>
2026-06-08 06:18:55 +03:00
..

rbxl-importer

Конвертер Roblox .rbxl карт в проекты Rublox. Состоит из:

  • Python-парсер Roblox Binary Level формата (v0+)
  • Asset downloader с дедупликацией (Marfusha proxy + .ROBLOSECURITY cookie)
  • Mesh→GLB конвертер (Roblox .mesh v1-v5)
  • Roblox-LUA runtime (wasmoon, реализован в репо rublox/player)
  • Flask API + React UI модалка в rublox/studio

Архитектура

[Студия]                                 [VM 130 rbxl-importer S1]
  user drops .rbxl              ┌─────────────────────────────┐
        ↓                       │ Flask  (port 8690)          │
  POST /api-rbxl/...   ─────────┤  ├ analyze: parser + report│
        ↓                       │  └ create: parser + конверт│
  redirect /edit/<id>           │     + asset_downloader     │
                                │     + mesh→glb              │
                                │                             │
                                │ Redis (preview cache)       │
                                │ nginx (assets.rublox.pro)   │
                                │ /opt/roblox-assets/         │
                                └─────────────────────────────┘
                                              ↓
                                  [Marfusha proxy 85.192.61.244:39237]
                                              ↓
                                  Roblox CDN (assetdelivery.roblox.com)
                                              ↓
                                  Ассеты ← .ROBLOSECURITY cookie auth

Структура

rbxl-importer/
  src/
    rbxl_binreader.py    — низкоуровневое чтение (deinterleave, zigzag, roblox float)
    rbxl_types.py        — декодеры 28+ PROP типов (Vector3, CFrame, Color3, ...)
    rbxl_parser.py       — парсер chunks → RobloxModel
    converter.py         — RobloxModel → Rublox project_data
    asset_downloader.py  — скачка с Roblox CDN, дедуп через roblox_assets
    asset_proxy.py       — режимы proxy: disabled/direct/http_proxy/cloudflare_worker
    mesh_converter.py    — Roblox .mesh v1-v5 → GLB
    app.py               — Flask endpoints
  sql/
    001_roblox_assets.sql — таблицы roblox_assets, roblox_asset_usage, roblox_imports
  reference_files/        — тестовые .rbxl
  tests/                  — unit-тесты

Поток импорта

  1. Юзер (МИН) загружает .rbxl через модалку в студии.
  2. POST /import/rbxl/analyze → парсер, отчёт, preview_hash в Redis.
  3. Юзер видит: число объектов, скриптов, ассетов, классов.
  4. POST /import/rbxl/create с title:
    • Парсим → конвертим RobloxModel → project_data.
    • Скачиваем все rbxassetid:// ассеты (mesh/texture/sound).
    • Mesh → GLB через mesh_converter.
    • INSERT в kubikon3d_projects (status=draft, is_test=true).
  5. Редирект на /edit/<project_id> — открывается в студии.
  6. Если есть Lua-скрипты (kind: 'roblox-lua') — плеер запускает их через RobloxLuaSandbox (wasmoon).

Запуск (на VM 130)

systemctl start rbxl-importer
systemctl status rbxl-importer
# логи:
journalctl -u rbxl-importer -f

ENV

Переменная Значение
PG_DSN DSN Postgres storys_db (через autossh туннель S1→S2)
REDIS_URL redis://127.0.0.1:6379/0 (локальный Docker)
STORAGE_ROOT /opt/roblox-assets
PUBLIC_ASSET_BASE https://assets.rublox.pro/roblox
ROBLOX_PROXY_MODE http_proxy
ROBLOX_HTTP_PROXY Marfusha xray HTTP proxy
ROBLOX_SECURITY_COOKIE .ROBLOSECURITY от Roblox-аккаунта МИНа

Тестовый импорт

# analyze (file=Easy Obby)
curl -X POST -H "X-Auth-Override: 1" \
    -F "file=@reference_files/easy_obby.rbxl" \
    http://localhost:8690/import/rbxl/analyze

# create
curl -X POST -H "X-Auth-Override: 1" -H "Content-Type: application/json" \
    -d '{"preview_hash":"<from_analyze>", "title":"Easy Obby"}' \
    http://localhost:8690/import/rbxl/create

Ограничения / TODO

  • Roblox auth обязателен для большинства ассетов (с 2024 года). Используется .ROBLOSECURITY cookie аккаунта МИНа.
  • GUI (ScreenGui, Frame, TextLabel) пока пропускается в конвертере (skipped).
  • Animation/KeyframeSequence требуют отдельной обработки.
  • CSG: parsing есть, но конверт в GLB не реализован — пока деградация в bbox cube.
  • Terrain (voxel) — конвертация в robloxTerrain поле пока заглушка.

Авторские права

Эта тест-фича для МИНа только. Юзер подтверждает право использовать содержимое карты при загрузке. Не открывать для публичных пользователей без юр-проверки.