diff --git a/RUBLOX_LUA_API_CHANGELOG.md b/RUBLOX_LUA_API_CHANGELOG.md index c7e99f6..2a15502 100644 --- a/RUBLOX_LUA_API_CHANGELOG.md +++ b/RUBLOX_LUA_API_CHANGELOG.md @@ -62,6 +62,11 @@ ContextActionResult, UserInputState, BorderMode, FormFactor. аргумента раньше делал tight loop без yield → WASM stack overflow ("memory access out of bounds"). +- **Уважаем `enabled: false`** в Roblox-метадате. Roblox-скрипты с + `Disabled = true` — это шаблоны для клонирования (`script.Clean:Clone()`), + не должны запускаться при старте. `parseRobloxLuaMeta()` парсит JSON + из второй строки packed-кода, при `enabled=false` скрипт идёт в `rbxlSkipped`. + ### Надо ли портировать в JS-движок? ✅ **Да, всё** — это базовый Roblox-совместимый API, который должен работать diff --git a/src/editor/engine/GameRuntime.js b/src/editor/engine/GameRuntime.js index 3d34ba6..5e65d13 100644 --- a/src/editor/engine/GameRuntime.js +++ b/src/editor/engine/GameRuntime.js @@ -19,7 +19,7 @@ import { ScriptSandbox } from './ScriptSandbox'; import { STORYS_addres } from '../../api/API'; import { PhysicsWorld } from './PhysicsWorld'; import { LabelManager } from './LabelManager'; -import { handleLuaCommand, unpackRobloxLuaCode } from './rbxl-lua-integration.js'; +import { handleLuaCommand, unpackRobloxLuaCode, parseRobloxLuaMeta } from './rbxl-lua-integration.js'; import { LuaSharedSandbox } from './lua/LuaSharedSandbox.js'; export class GameRuntime { @@ -128,6 +128,11 @@ export class GameRuntime { for (const s of scripts) { if (s && typeof s.code === 'string' && s.code.startsWith('// @roblox-lua')) { if (!runImportedRbxl) { rbxlSkipped++; continue; } + // Уважаем поле enabled=false из Roblox-метадаты: такие скрипты + // были disabled-шаблоны (для клонирования через :Clone()), их + // запуск немедленно крашит coroutine (WASM access out of bounds). + const meta = parseRobloxLuaMeta(s.code); + if (meta && meta.enabled === false) { rbxlSkipped++; continue; } const luaSource = unpackRobloxLuaCode(s.code); if (luaSource && luaSource.trim()) { luaUserBatch.push({ diff --git a/src/editor/engine/rbxl-lua-integration.js b/src/editor/engine/rbxl-lua-integration.js index ae1ce2e..cbef7f7 100644 --- a/src/editor/engine/rbxl-lua-integration.js +++ b/src/editor/engine/rbxl-lua-integration.js @@ -20,6 +20,20 @@ export function unpackRobloxLuaCode(code) { return code.slice(start, closeIdx); } +/** Парсит JSON-метадату из 2-й строки packed-кода (`// {"roblox_class":..., "enabled": true}`). */ +export function parseRobloxLuaMeta(code) { + if (typeof code !== 'string') return null; + const lines = code.split('\n'); + if (lines.length < 2) return null; + const metaLine = lines[1]; + if (!metaLine.startsWith('// ')) return null; + try { + return JSON.parse(metaLine.slice(3)); + } catch (_) { + return null; + } +} + /** Сцена → snap для shim'а (workspace:GetChildren). */ export function buildLuaSceneSnap(primitives) { const out = { primitives: {} };