# Lua API — журнал изменений Файл фиксирует **что было добавлено в Lua-runtime** при работе с реальными Roblox-играми. Цель — потом продублировать тот же API для **JS-движка** (на будущее, сейчас работаем только с Lua). Формат: дата + что и почему + куда добавлено + надо ли портировать в JS. --- ## 2026-06-08 — Итерация 4: Spawn-fix + философия импорта **Контекст:** МИН подтвердил после ROBLOX Battle: 100% покрытие Lua-скриптов из Roblox не получится (наш wasmoon не yield'ит из JS C-call boundary, старый Roblox-pattern WaitForChild через ChildAdded:wait тривиально вешает страницу). **Цель импорта сменилась**: показать геометрию и базовые интеракции, а не полную скриптовую логику. ### Spawn fix (карта проекта 2853) После переимпорта одной из карт игрок появлялся **внутри Anchored геометрии** (стена/пол), не мог двигаться. Причина: SpawnLocation в старых .rbxl ставится впритык к плите (Y+0.5), наш отступ +1.5 не спасал от толстых Floor'ов 2-3 units high. Anchored=True (наш force-fix) не давал выпрыгнуть. Фиксы в `converter.py`: 1. **SpawnLocation +5** вместо +1.5. Если spawn внутри толстого пола — гравитация уронит обратно за 1 кадр, не страшно. Если выше — отлично. 2. **Auto-fallback** если SpawnLocation в карте НЕ был (или дефолт остался `(0, 2, 0)`): ```python max_top = max(p['y'] + p['sy']/2 for p in primitives) scene['spawnPoint'] = {x: 0, y: max_top + 5, z: 0} ``` Игрок появляется над самой высокой Part'ой → падает на крышу. ### Философия импорта (зафиксировано как принцип) **Цель импорта .rbxl** = показать геометрию и сцену, а не воспроизвести скриптовое поведение. Что работает (важно): - ✅ Все примитивы (Part/Wedge/CornerWedge/Truss/Union/MeshPart) - ✅ Цвета через BrickColor (расширенная палитра 120 цветов) - ✅ Anchored=True для всех (карта не рассыпается) - ✅ SpawnLocation с правильным Y (игрок не в стене) - ✅ Корректный CFrame YXZ (мостики/wedge'и стоят правильно) - ✅ Скайбокс, освещение, экспозиция/контраст через слайдеры - ✅ Простые Touched-скрипты (Bouncer, BattleArmor, KillBrick) - ✅ Tools.Equipped/Activated handlers (часть оружия) Что НЕ воспроизводится (принимаем): - ❌ Сложные RoundScript / GameClock / Spawner / KillFeed-логика - ❌ WaitForChild через while+:wait() паттерны (regex-фильтр пропускает) - ❌ Регенерация построек (Regenerate*) — не нужна т.к. Anchored - ❌ LeaderboardV3 с DataStore (пропускается) - ❌ Сетевые RemoteEvent/RemoteFunction (single-player только) ### Когда снова работать со скриптами Если попадётся **новая карта (2015+)** — `WaitForChild` встроен в API, наш regex-фильтр не сработает. Скрипты пройдут больше и будут работать лучше. Старые карты (2007-2010) принципиально ограничены. ### Что НЕ делать - Не пытаться "ещё раз" решить yield-across-C-boundary через debug.sethook или pcall-трюки. Проверено — не работает с wasmoon. - Не переписывать wasmoon — это месяцы работы. - Не сужать regex-фильтр в надежде запустить ещё пару скриптов — лучше пусть пропустится лишний, чем висит страница. ### Что делать дальше - Идти по .rbxl из Desktop/RBLX/ как пользователь. - На каждой карте проверять: геометрия загрузилась? игрок ходит? видна? - Если виснет — добавлять regex-паттерн в фильтр. - Если игрок застрял — улучшать spawn-fallback. - Если падают конкретные API — реализовывать в shim (как Mouse.Icon, BodyVelocity-bouncer, leaderstats). ### В JS ✅ Все фиксы spawn + философия общая для студии и плеера. --- ## 2026-06-08 — Итерация 3: ROBLOX Battle (arch1_ROBLOX_Battle_v2.rbxl, проект 2851) **Контекст:** PvP-арена 2009 в XML, 1677 примитивов, 66 скриптов, 4 команды (TeamBeacon), 5 оружий, 12 батутов, KillFeed, раунды. ### Реализовано 11 механик из 14 1. **Teams** — game.Teams сервис + Team-инстансы, эвристика TeamBeacon-Model в converter.py → автоматически создаёт 4 команды по имени. 2. **Leaderstats UI** — IntValue.Value реактивно через Object.defineProperty, при Parent=leaderstats шлёт leaderstatSet → существующий LeaderstatsManager. 3. **BindableFunction/RemoteFunction** + Message/Hint классы с реактивным Text. 4. **KillFeed UI** + creator-tag tracking в Humanoid.TakeDamage. DOM-overlay. 5. **SpawnLocation.TeamColor** → scene.team_spawns[]. 6. **Tool/Model:Clone()** + :MakeJoints/:BreakJoints/:Remove no-op. 7. **Creator-tag**: ObjectValue.Name='creator' проверяется на Health=0. 8. **RegenerationScript** — no-op skip по имени (Anchored=True держит). 9. **BattleArmor** — реактивный Humanoid.MaxHealth/Health/WalkSpeed/JumpPower. 10. **WinGui/FireButton** через GuiManager. 11. **AdminConsole** — no-op. 12. **Bouncer** — BodyVelocity.Y > 10 + Parent=Torso → playerSet jumpVelocity. 14. **Mouse.Icon** → CSS cursor через canvas.style.cursor. Также добавлены: **tick/time/delay/spawn/LoadLibrary** legacy globals, **SpecialMesh/BlockMesh/CylinderMesh/FileMesh** Instance.new стабы. ### Новый модуль RbxlHudOverlay.js DOM-оверлей поверх canvas с KillFeed (правый верх, fade 5с) + Message (центр верх) + WinGui (центр). Lazy-создаётся. ### Tight-loop защита (КРИТИЧНО) Roblox 2009 паттерн: ```lua while not parent:FindFirstChild(name) do parent.ChildAdded:wait() end ``` Наш Signal:wait() возвращает синхронно — цикл бесконечный, страница виснет. **Не можем yield** из JS-функции через wasmoon C-call boundary. Перепробовали: - debug.sethook(yield, 'i', N) — внутри C-call падает с `yield across C-call`. - pcall(coroutine.yield) — ошибка ловится, счётчик не сбрасывается, вис. **Финал**: regex-фильтр в GameRuntime.js пропускает скрипты с этими паттернами. Из 66 скриптов 37 пропущены, 29 работают. Жертвы: RoundScript, GameClock, Spawner, KillFeed, LeaderboardV3, оружие Launcher/Sword/Slingshot/Cannon. ### CFrame YXZ Euler Переписал `to_euler_xyz` в `rbxl_types.py` под Babylon YXZ convention: rx=asin(-r12), ry=atan2(r02,r22), rz=atan2(r10,r11) + gimbal-lock guard. Раньше извлекал XYZ-Euler, Babylon применял как YXZ — мостики поворачивались криво. ### Persistence настроек света BabylonScene.serialize/loadFromState сохраняют scene.lighting: sunIntensity, hemiIntensity, sceneAmbient, exposure, contrast, saturation. ### Известные баги - `memory access out of bounds` (1 раз) — WASM-crash одного скрипта. - `Cannot read properties of null ('then')` — wasmoon promise-detection, скрипт init крашится но не блокирует. - 0 teams при загрузке старого проекта — нужен переимпорт. ### В JS ✅ Всё: Teams формат общий, KillFeed/Message HUD общий для студии+плеера. --- ## 2026-06-08 — Итерация 2: Crossroads (arch1_Original_Crossroads.rbxl, проект 2827) **Контекст:** Классическая Roblox-карта 2009 года для PvP, **XML-формат** .rbxl (старее бинарного). 877 instances, 777 Part, 83 Model. Состоит из 4 зон: крепость (Castle), дом (House Platform), деревья, дорожки крест-накрест. 2 скрипта: «Regenerate Playground» и «Regenerate Castle» — периодически удаляют и восстанавливают постройки (для PvP). ### Главное: XML-парсер для .rbxl `rbxl-importer/src/rbxl_xml_parser.py` (новый файл, ~330 строк): - `is_xml_rbxl(blob)` — детект по `N` — особый случай: в старом XML цвет лежит как int с именем `BrickColor`, заворачиваем в `BrickColor(code=N)`. В `app.py` добавлен автодетект формата: ```python is_binary = blob.lstrip().startswith(b' Падение.** Лучше пустой stub-метод чем `nil error`. 2. **Сигналы (`Connect`/`Fire`) всегда есть на любом объекте.** 3. **Coloncall совместимость.** Если есть `Foo.Bar`, обычно делаем и `Foo:Bar` (lowercase) как alias. 4. **При добавлении нового Instance-типа** — давай ему **все типичные поля** сразу, не только те что нужны прямо сейчас (Equipped + Unequipped + Activated вместе, даже если скрипт юзает только Equipped). 5. **Логировать сюда после каждой итерации** — что было добавлено и из какой игры.