studio/src/api/rbxlImporterApi.js
min 16223e06ef feat(rbxl): выбор режима скриптов в модалке импорта
3 опции в модалке (только если в карте есть скрипты):
- 'disabled' (default) — скрипты импортируются с enabled=false в метадате
  → GameRuntime их не запускает, но видны в иерархии для чтения
  как референс при написании своих Lua-скриптов.
- 'enabled' — скрипты активны (старое поведение). Может вешать игру
  на старых Roblox 2007-2010 паттернах.
- 'skip' — scripts[] обнуляется, чистый импорт только геометрии.

Реализация:
- RbxlImportModal.jsx: state scriptsMode + radio-блок над названием игры,
  показывается только если report.scripts_total > 0.
- rbxlImporterApi.js: передача scripts_mode в /import/rbxl/create.
- app.py: _apply_scripts_mode() патчит JSON-метадату на 2-й строке
  packed-кода скрипта (или удаляет scripts[] для 'skip').

GameRuntime уже умеет уважать meta.enabled === false — пропускает скрипт.

Deploy app.py на VM 130.
2026-06-08 21:20:01 +03:00

74 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* rbxlImporterApi.js — клиент для rbxl-importer (Flask API на VM 130).
*
* Endpoints:
* POST /api-rbxl/import/rbxl/analyze — анализ .rbxl, возвращает report + preview_hash
* POST /api-rbxl/import/rbxl/create — скачать ассеты, создать проект
* GET /api-rbxl/health — healthcheck
*/
import { RBXL_addres } from './API.js';
// На dev (localhost) backend ещё не интегрирован с user-service для JWT-парсинга.
// Используем dev override: явно передаём user_id. В prod NPM или user-service
// сами выставят X-User-Id из JWT.
const IS_DEV = typeof window !== 'undefined'
&& (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1');
function authHeaders() {
const token = localStorage.getItem('Authorization') || '';
const headers = { 'Authorization': token };
if (IS_DEV) {
// Достаём user_id из JWT для dev (без validation — backend на dev доверяет).
try {
const payload = JSON.parse(atob(token.split('.')[1] || ''));
if (payload && payload.id != null) headers['X-Auth-Override'] = String(payload.id);
} catch (e) {
// если JWT не парсится — забыли залогиниться, всё равно отправим что-то
}
}
return headers;
}
/**
* Анализ .rbxl. Принимает File (из <input type="file">) или Blob.
* Возвращает { preview_hash, report }.
*/
export async function analyzeRbxl(file) {
const fd = new FormData();
fd.append('file', file, file.name || 'upload.rbxl');
const resp = await fetch(`${RBXL_addres}/import/rbxl/analyze`, {
method: 'POST',
headers: authHeaders(),
body: fd,
});
if (!resp.ok) {
const text = await resp.text();
throw new Error(`analyze failed (${resp.status}): ${text}`);
}
return resp.json();
}
/**
* Создаёт проект из preview_hash. Возвращает { project_id, redirect, assets_downloaded, assets_failed }.
*/
export async function createRbxlProject(previewHash, title, opts = {}) {
const resp = await fetch(`${RBXL_addres}/import/rbxl/create`, {
method: 'POST',
headers: { ...authHeaders(), 'Content-Type': 'application/json' },
body: JSON.stringify({
preview_hash: previewHash,
title: title || '',
// 'disabled' (default) — импортнуть выключенными, читать можно
// 'enabled' — попытаться запустить (может вешать карту)
// 'skip' — не импортировать совсем
scripts_mode: opts.scriptsMode || 'disabled',
}),
});
if (!resp.ok) {
const text = await resp.text();
throw new Error(`create failed (${resp.status}): ${text}`);
}
return resp.json();
}