studio/RUBLOX_LUA_API_CHANGELOG.md

8.5 KiB
Raw Blame History

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 если есть toolNamescript.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.mousedownmouseButton1Down + 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. Логировать сюда после каждой итерации — что было добавлено и из какой игры.