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.
74 lines
3.0 KiB
JavaScript
74 lines
3.0 KiB
JavaScript
/**
|
||
* 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();
|
||
}
|