# Lua API — журнал изменений Файл фиксирует **что было добавлено в Lua-runtime** при работе с реальными Roblox-играми. Цель — потом продублировать тот же API для **JS-движка** (на будущее, сейчас работаем только с Lua). Формат: дата + что и почему + куда добавлено + надо ли портировать в JS. --- ## 2026-06-08 — Итерация 1: RayGun (проект 2792, 9 скриптов) **Контекст:** Roblox-Tool пушка-стрелялка, использует Tool-API, Lighting, Mouse, Welds, BodyForce, BrickColor, IntValue для leaderboard. ### Добавлено в `RobloxShim.js` **Глобалы:** - `BrickColor.new("Bright red")` + ~25 цветов (White, Black, Bright red/blue/green, Pink, Brown, Reddish brown, Cyan, Magenta и др.). Возвращает `{Color, Name, R, G, B}`. - `Ray.new(origin, direction)` — для raycast (заглушка структуры). - `Region3.new(min, max)` — куб (заглушка). - `TweenInfo.new(time, easingStyle, easingDirection, repeatCount, reverses, delayTime)` - `NumberSequence`, `ColorSequence`, `NumberRange`, `Rect` — конструкторы-стабы. **Enum расширения:** InfoType, SortOrder, FillDirection, Font, TextXAlignment/TextYAlignment, ScaleType, AspectType, PartType, SurfaceType, ContextActionResult, UserInputState, BorderMode, FormFactor. **`game` методы:** - `game:service(name)` (lowercase alias на GetService) — старый Roblox API. - `game.GetServiceFromName` = alias. - `game.JobId/PlaceId/GameId/CreatorId/CreatorType` — stub fields. **Lighting:** - `Brightness`, `ClockTime`, `TimeOfDay`, `OutdoorAmbient`, `FogStart/End/Color`. - `GetMinutesAfterMidnight()`, `SetMinutesAfterMidnight(m)`. - `GetMoonDirection()`, `GetSunDirection()`. **Players:** - `GetPlayers()`, `GetPlayerFromCharacter(char)`, `playerFromCharacter` alias. - `PlayerAdded`, `PlayerRemoving`, `ChildAdded` signals. **Instance.new новые типы:** - `Tool` / `HopperBin` — Equipped/Unequipped/Activated/Deactivated signals, GripForward/Right/Up/Pos, CanBeDropped, RequiresHandle, ToolTip. - `IntValue` / `NumberValue` / `BoolValue` / `StringValue` / `ObjectValue` / `CFrameValue` / `Vector3Value` / `Color3Value` / `BrickColorValue` / `RayValue` — `.Value` + `.Changed` сигнал. - `BodyForce` / `BodyVelocity` / `BodyPosition` / `BodyGyro` / `BodyAngularVelocity` / `BodyThrust` — `.force`, `.Velocity`, `.MaxForce`, `.P/.D`. - `Weld` / `WeldConstraint` / `Motor6D` / `Snap` / `HingeConstraint` / `BallSocketConstraint` / `RopeConstraint` / `SpringConstraint` — Part0/Part1/C0/C1/Enabled. - `Sparkles` / `ParticleEmitter` / `Smoke` / `Fire` / `Trail` / `Beam` / `PointLight` / `SurfaceLight` / `SpotLight` — Enabled/Color/Rate/Lifetime/Brightness/Range. - `Mouse` — Button1Down/Up, Button2Down/Up, Move, KeyDown/Up, WheelForward/Backward, Icon, Hit (Position), Target, TargetSurface, X/Y, ViewSizeX/Y. ### Исправлено - `rbx_wait(sec)`: минимум 0.016с (1 кадр). `while true do wait() end` без аргумента раньше делал 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`. ### Tool/Backpack/Mouse flow (Шаг 1) Контекст: Roblox-Tool это объект который попадает в Backpack игрока, при экипировке (клавиша 1-9) фейерит Tool.Equipped с настоящим Mouse, скрипты внутри Tool слушают MouseButton1Down/KeyDown. **В `RobloxShim.js`:** - `localPlayer.Backpack` — инвентарь. - `localPlayer:GetMouse()` → playerMouse с Button1Down/KeyDown/Hit.Position. - Внутренний `allTools[]` registry + `equippedTool` слот. - `Instance.new('Tool')` теперь: - создаёт виртуальный `Handle` (Part внутри Tool); - регистрирует в `allTools[]`; - шлёт `toolRegistered {index, name}` в GameRuntime. - `fireGlobalEvent` обрабатывает: `equipTool`, `unequipTool`, `toolActivated`, `toolDeactivated`, `mouseButton1Down`/`Up`, `keyDown`/`Up`. - `__rbxl_get_tool_by_name(name)` — для script.Parent резолва. **В `LuaSharedSandbox.js`:** - `addScript(id, code, target, name, {toolName})` — расширенная сигнатура. - В `_startSingleScript` если есть `toolName` — `script.Parent` = виртуальный Tool. **В `GameRuntime.js`:** - Эвристика: скрипты с `target=null` и содержащие `(script.Parent|Tool).(Equipped|Unequipped|Activated|Deactivated)` → получают `toolName='Tool'`, группируются в один общий Tool. - `_registerRbxlTool(payload)` — кладёт item в InventoryUI.hotbar, слушает `slot` event → шлёт `equipTool`/`unequipTool`. - `canvas.mousedown` → `mouseButton1Down` + `toolActivated` с raycast Hit. - `_raycastFromCamera()` — простой ray из камеры на 50 unit вперёд. **Надо ли в JS?** ✅ Да — Tool/Backpack/Mouse это базовый Roblox-game-loop. ### Импорт изменений в converter.py (не задеплоено) Файл изменён локально, но importer на VM 130 — не обновлён. Когда придёт время деплоя, ключевые правки: - `_collect_tool(inst)` — собирает `scene['tools'][]` из Tool/HopperBin; - `_find_ancestor_tool(inst)` — определяет в каком Tool лежит Script; - В `_convert_script` добавлено поле `tool_id` в метадату. Это уберёт необходимость эвристики на стороне studio. ### Надо ли портировать в JS-движок? ✅ **Да, всё** — это базовый Roblox-совместимый API, который должен работать независимо от языка скриптов. **JS-эквивалент будет такой же структурой:** - `BrickColor.new("Bright red")` → `new BrickColor("Bright red")` - `Tool` Equipped/Unequipped → JS-EventEmitter методы - BodyForce/Weld/Sparkles → JS-классы с теми же полями - Mouse — глобальный объект `game.mouse` или через `player:GetMouse()`. --- ## Куда добавляется API | Источник | Файл | Что туда идёт | |----------|------|---------------| | Глобалы (Vector3, Color3, BrickColor, Enum) | `RobloxShim.js` через `global.set` | Конструкторы, Enum-таблицы | | Instance.new типы | `RobloxShim.js` в ветке `global.set('Instance', {new: ...})` | Tool, BodyForce, Weld, Sparkles и т.д. | | Сервисы | `RobloxShim.js` через `makeService(name)` | Lighting, Players, RunService и т.д. | | Wait/Task | `RobloxShim.js` в Lua-prelude (`lua.doStringSync`) | rbx_wait, task.wait | | Setter Part-свойств | `newPart()` через `Object.defineProperty` | Position, Color, Anchored шлют partSet | | Команды от Lua к Babylon | `rbxl-lua-integration.js` `handleLuaCommand` | partSet, sceneCreate, sceneDelete | --- ## Принципы расширения API 1. **No-op > Падение.** Лучше пустой stub-метод чем `nil error`. 2. **Сигналы (`Connect`/`Fire`) всегда есть на любом объекте.** 3. **Coloncall совместимость.** Если есть `Foo.Bar`, обычно делаем и `Foo:Bar` (lowercase) как alias. 4. **При добавлении нового Instance-типа** — давай ему **все типичные поля** сразу, не только те что нужны прямо сейчас (Equipped + Unequipped + Activated вместе, даже если скрипт юзает только Equipped). 5. **Логировать сюда после каждой итерации** — что было добавлено и из какой игры.