diff --git a/rbxl-importer/src/__pycache__/app.cpython-314.pyc b/rbxl-importer/src/__pycache__/app.cpython-314.pyc new file mode 100644 index 0000000..2b0e391 Binary files /dev/null and b/rbxl-importer/src/__pycache__/app.cpython-314.pyc differ diff --git a/rbxl-importer/src/app.py b/rbxl-importer/src/app.py index b9788db..4e31893 100644 --- a/rbxl-importer/src/app.py +++ b/rbxl-importer/src/app.py @@ -210,6 +210,12 @@ def create(): data = request.get_json(silent=True) or {} preview_hash = data.get('preview_hash') title = (data.get('title') or '').strip() or 'Импортировано из Roblox' + # scripts_mode: 'disabled' (default) — оставить в проекте, но enabled=False + # 'enabled' — попытаться запустить, может вешать + # 'skip' — не импортировать совсем + scripts_mode = data.get('scripts_mode', 'disabled') + if scripts_mode not in ('disabled', 'enabled', 'skip'): + scripts_mode = 'disabled' if not preview_hash: return jsonify({'error': 'preview_hash required'}), 400 @@ -274,6 +280,10 @@ def create(): # Подставляем URLs в project_data _resolve_asset_urls(project_data, asset_url_map) + # Применяем scripts_mode: меняем поле enabled в метадате каждого скрипта + # либо удаляем все скрипты полностью. + _apply_scripts_mode(project_data, scripts_mode) + # Создаём проект в kubikon3d_projects # Используем bridge на user-service / storys API, ИЛИ напрямую в storys_db. # Прямой INSERT — проще для MVP. id автогенерируется. @@ -335,5 +345,46 @@ def _resolve_asset_urls(project_data: dict, asset_map: dict) -> None: snd['url'] = asset_map[rid] +def _apply_scripts_mode(project_data: dict, mode: str) -> None: + """Применяет режим scripts_mode к проекту. + + mode='disabled' (default): для каждого скрипта меняем JSON-метадату + на 2-й строке packed-кода — выставляем enabled=False. GameRuntime + уже умеет уважать этот флаг и не запускает. + mode='enabled': оставляем как было (как пришло из конвертера). + mode='skip': удаляем все scripts из scene.scripts полностью. + """ + scene = project_data.get('scene', {}) + scripts = scene.get('scripts', []) + if not scripts: + return + + if mode == 'skip': + scene['scripts'] = [] + return + + if mode == 'enabled': + return # ничего не делаем + + # mode == 'disabled' — патчим метадату каждого скрипта. + # Формат packed-кода (см. converter._convert_script): + # "// @roblox-lua\n// {JSON}\n/* lua_source:\n...source...\n*/\n" + for s in scripts: + code = s.get('code', '') + lines = code.split('\n', 2) + if len(lines) < 2 or not lines[0].startswith('// @roblox-lua'): + continue + meta_line = lines[1] + if not meta_line.startswith('// '): + continue + try: + meta = json.loads(meta_line[3:]) + meta['enabled'] = False + new_meta_line = '// ' + json.dumps(meta, ensure_ascii=False) + s['code'] = lines[0] + '\n' + new_meta_line + '\n' + (lines[2] if len(lines) > 2 else '') + except (json.JSONDecodeError, ValueError): + continue + + if __name__ == '__main__': app.run(host='0.0.0.0', port=8690, debug=False) diff --git a/src/api/rbxlImporterApi.js b/src/api/rbxlImporterApi.js index 68675f2..fa7b762 100644 --- a/src/api/rbxlImporterApi.js +++ b/src/api/rbxlImporterApi.js @@ -52,11 +52,18 @@ export async function analyzeRbxl(file) { /** * Создаёт проект из preview_hash. Возвращает { project_id, redirect, assets_downloaded, assets_failed }. */ -export async function createRbxlProject(previewHash, title) { +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 || '' }), + 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(); diff --git a/src/components/RbxlImportModal.jsx b/src/components/RbxlImportModal.jsx index 8d137ec..9c3e5cd 100644 --- a/src/components/RbxlImportModal.jsx +++ b/src/components/RbxlImportModal.jsx @@ -26,6 +26,9 @@ export default function RbxlImportModal({ open, onClose, currentUserId, onCreate const [previewHash, setPreviewHash] = useState(null); const [title, setTitle] = useState(''); const [error, setError] = useState(null); + // Режим скриптов: 'disabled' (импортнуть выключенными — для чтения), + // 'enabled' (попытаться запустить — может вешать карту), 'skip' (удалить). + const [scriptsMode, setScriptsMode] = useState('disabled'); const fileInputRef = useRef(null); if (!open) return null; @@ -45,6 +48,7 @@ export default function RbxlImportModal({ open, onClose, currentUserId, onCreate const reset = () => { setFile(null); setReport(null); setPreviewHash(null); setTitle(''); setError(null); setAnalyzing(false); setCreating(false); + setScriptsMode('disabled'); }; const handleClose = () => { reset(); onClose?.(); }; @@ -88,7 +92,7 @@ export default function RbxlImportModal({ open, onClose, currentUserId, onCreate setCreating(true); setError(null); try { - const result = await createRbxlProject(previewHash, title); + const result = await createRbxlProject(previewHash, title, { scriptsMode }); onCreated?.(result); handleClose(); // редирект на редактор @@ -206,6 +210,58 @@ export default function RbxlImportModal({ open, onClose, currentUserId, onCreate + {report.scripts_total > 0 && ( +
+
+ Что делать со скриптами ({report.scripts_total} шт.)? +
+ + + +
+ )} +