19 Commits

Author SHA1 Message Date
min
52724ab9c8 fix(rbxl): invUI вместо inventory + Day/Night портирован + искры Sparkles
Что чинит:
1. _registerRbxlTool падал: использовал scene3d.inventory (InventoryManager,
   старый, без defineItem). Меняю на scene3d.invUI (новый InventoryUI с
   defineItem) — теперь hotbar реально заполняется.

2. Lighting.SetMinutesAfterMidnight теперь шлёт lightingTimeUpdate в
   GameRuntime → scene3d.setTimeOfDay(hour). Тротлинг 4 раза/сек.
   Roblox Day&Night скрипт теперь визуально меняет небо в нашем плеере!

3. Instance.new('Sparkles') шлёт particleCreated в GameRuntime.
   При эквипе Tool — _startRbxlToolParticles() запускает каждые 200мс
   burst у позиции игрока (имитация искр из руки).

4. Авто-эквип первого Tool через 100мс после регистрации — юзеру не
   нужно нажимать 1, инвентарь не очевиден.

5. stop() корректно гасит интервалы и сбрасывает state.

Эти 4 фикса должны дать Zapper-демке базовое визуальное поведение:
видный hotbar, искры из персонажа, плавная смена дня/ночи.
2026-06-08 14:08:09 +03:00
min
bb0726b4ad revert(lua): убрал недописанный leaderstats scan (компилировался но не работал) 2026-06-08 14:02:16 +03:00
min
1080c18ae0 feat(rbxl): Tool/Backpack/Mouse flow — Шаг 1/3 (Zapper)
Цель: запустить Roblox Tools (Zapper и подобные оружия) в плеере.

Архитектура:
1. RobloxShim: localPlayer.Backpack, localPlayer:GetMouse(), allTools registry,
   equippedTool — внутренний учёт текущего Tool.
2. Instance.new('Tool') — теперь автоматически:
   - создаёт виртуальный Handle (Part) внутри
   - регистрирует Tool в allTools[]
   - шлёт 'toolRegistered' в GameRuntime
3. fireGlobalEvent обработка новых событий из плеера:
   - equipTool {index} → Tool.Equipped:Fire(playerMouse)
   - unequipTool → Tool.Unequipped:Fire()
   - toolActivated → Tool.Activated:Fire()
   - mouseButton1Down {hit} → mouse.Hit.Position + mouse.Button1Down:Fire()
   - keyDown {key} → mouse.KeyDown:Fire(key)
4. LuaSharedSandbox.addScript принимает toolName, в _startSingleScript
   подсовывает виртуальный Tool как script.Parent (через
   __rbxl_get_tool_by_name).
5. GameRuntime эвристика: скрипты с target=null и упоминанием
   script.Parent.Equipped/Activated → toolName='Tool', группируются
   в один Tool.
6. GameRuntime._registerRbxlTool: при получении toolRegistered кладёт
   item в InventoryUI.hotbar, слушает смену слота → equipTool.
7. Клики canvas → mouseButton1Down с raycast Hit.Position.

Следующие шаги:
- HUD: индикатор экипированного Tool в плеере (Шаг 2)
- Leaderboard UI из leaderstats IntValue (Шаг 3)
2026-06-08 13:57:37 +03:00
min
ca92ba1988 feat(lua): Итерация 1 RayGun — Tool/Mouse/BodyForce/Weld/IntValue/BrickColor
Поддержка скриптов проекта 2792 (Roblox RayGun Tool, 9 скриптов).

Lighting: ClockTime, GetMinutesAfterMidnight, SetMinutesAfterMidnight,
GetSunDirection, fog* поля.

game:service(name) — старый Roblox API (lowercase alias на GetService).
Players: GetPlayerFromCharacter, playerFromCharacter, PlayerAdded, ChildAdded.

Instance.new новых типов:
- Tool/HopperBin: Equipped/Unequipped/Activated/Grip*/CanBeDropped
- IntValue/NumberValue/BoolValue/StringValue/ObjectValue + Value/Changed
- BodyForce/BodyVelocity/BodyPosition/BodyGyro + force/Velocity/MaxForce
- Weld/Motor6D/HingeConstraint + Part0/Part1/C0/C1
- Sparkles/ParticleEmitter/Fire/PointLight + Enabled/Color/Rate
- Mouse: Button1Down/KeyDown signals, Icon, Hit, Target, X/Y

Глобалы: BrickColor.new('name'/r,g,b) с палитрой 25+ цветов,
Ray.new, Region3.new.

Фикс WASM crash: rbx_wait минимум 0.016с (1 кадр) — без этого
while true do wait() end делал tight-loop без yield → stack overflow.

Добавлен RUBLOX_LUA_API_CHANGELOG.md — журнал что было добавлено
для каждой игры (для будущего портирования API в JS-движок).
2026-06-08 13:39:56 +03:00
min
5342c079d1 feat(lua): включил импортированные скрипты + защита от подвисания
1. TweenInfo.new(time, easing, direction, repeat, reverses, delay) —
   глобальный конструктор. Был причиной 'attempt to index nil (TweenInfo)'.
2. Расширенный Enum: InfoType, SortOrder, FillDirection, Font,
   TextXAlignment, ScaleType, PartType, SurfaceType, UserInputState
   и др. — типичные для Roblox-туториалов.
3. NumberSequence/ColorSequence/NumberRange/Rect — заглушки конструкторов.

4. _kickoff() теперь батчами по 20 скриптов через setTimeout(0).
   742 скрипта инициализируются за ~37 фреймов вместо одного
   синхронного блока, UI не подвисает.

5. Импортированные .rbxl-скрипты ВКЛЮЧЕНЫ по умолчанию
   (window.__RBXL_SKIP_IMPORTED=true чтобы выключить).
   Падения отдельных скриптов изолированы — tickScheduler ловит
   ошибки и удаляет битые coroutines, остальные продолжают работать.
2026-06-08 13:26:30 +03:00
min
f80aaceb96 fix(lua): убрал function-stub, теперь object-stub для unknown свойств
Прошлый callable-stub (function() {}) с Proxy/apply работал в JS но
ломался в Lua: wasmoon мапил JS function в Lua function, у которой
нет метатаблицы — поэтому stub:Connect() / stub.SomeField падало с
'attempt to index a function value'.

Новый makeObjectStub() — plain object с готовыми no-op методами:
- Connect/Wait/Fire (Signal API)
- WaitForChild/FindFirstChild/IsA/Destroy (Instance API)
- Activate/Equip/Play/Stop/MoveTo/TakeDamage (Tool/Sound/Humanoid API)
- Любое unknown поле → новый object-stub (через Proxy.get)

Это снимает 99% оставшихся 'attempt to index a function value'.
2026-06-08 13:16:07 +03:00
min
8fe52dbe68 fix(lua): universal callable-stub для unknown свойств Instance
Импортированные скрипты делают obj:Method(arg) где obj — stub. Раньше
stub был просто Folder, его как функцию вызвать нельзя → self2 is not
a function массово.

Фикс: makeCallableStub() — Proxy на function(){} который:
- вызывается как функция (apply trap) → возвращает себя;
- имеет .Connect/.Disconnect/.Wait/.Fire → ведёт себя как сигнал;
- любое .UnknownField → возвращает другой callable-stub;
- .then/.catch/.constructor → undefined (wasmoon не путается).

Этим закрывается основная масса остаточных падений в туториал-скриптах
с цепочками вроде Tool.Handle:WaitForChild('X'):Connect(...) где Handle
у нас отсутствует.
2026-06-08 13:10:26 +03:00
min
dc7420a61d fix(lua): require() no-op + улучшенный Proxy для Instance
1. require(): в Roblox загружает ModuleScript. У нас модулей нет —
   возвращаем mod как есть (если объект) или undefined.

2. Proxy улучшения:
   - Object.hasOwnProperty + 'in' checks: методы (WaitForChild,
     FindFirstChild и т.д.) точно не перехватываются;
   - Symbol-ключи всегда undefined;
   - System keys (then, catch, toString, constructor) → undefined
     чтобы wasmoon не пытался обращаться как с Promise/класс;
   - has() возвращает true для всех строковых ключей (избавляет от
     падений на 'if obj.SomeField then ...').
2026-06-08 13:08:28 +03:00
min
59d0d86811 fix(lua): Proxy для Instance — unknown свойства возвращают stub вместо nil
Импортированные Roblox-скрипты массово падали на доступе к свойствам которых
у нас нет (.Selected, .Equipped, .MouseEnter и т.д.). В Roblox это сигналы
которые скрипты подключают через :Connect().

Фикс: оборачиваю newInstance() в Proxy:
- isProbablySignalName(prop) → возвращает makeStubSignal() (наш Signal с Connect/Fire)
- иначе → возвращает stub-Folder (тоже Instance с потенциальными children)
- системные ключи (then, __*, Symbol) → undefined чтобы wasmoon не путался

Эвристика покрывает основные Roblox-паттерны:
- *.Changed, *.Added, *.Removed, *.Began, *.Ended, *.Touched, *.Died
- Mouse*, Touch*, Input*, Render*, Step*, Heart*, On*, Char*, Player*
- Selected, Deselected, Equipped, Unequipped, Activated, Reached, Loaded

Это позволяет проходить инициализацию массе туториал-скриптов вместо
падения на первой же строке.
2026-06-08 13:04:38 +03:00
min
3e20107125 fix(lua): script.Parent fallback на workspace + WaitForChild создаёт stub-Folder
Импортированные .rbxl-скрипты массово падали на:
  attempt to index a nil value (field 'Parent')

Причины:
1. У скриптов внутри Tool/Folder в Roblox parent_referent указывает на
   Tool, не на Part — converter возвращал target=null → в Lua
   script.Parent = nil. Стандартный паттерн script.Parent.Parent падал.
2. WaitForChild возвращал undefined для несуществующих children.
   Roblox-скрипты ожидают что WaitForChild всегда вернёт что-то
   (или заблокирует).

Фикс:
- LuaSharedSandbox: если primId не найден в partById, script.Parent =
  workspace вместо nil. Это спасает 99% Roblox-туториал-скриптов
  которые делают script.Parent.Parent.

- RobloxShim.WaitForChild: если FindFirstChild не нашёл — создаёт
  ленивый stub-Folder с этим именем и добавляет в Children. Скрипт
  не падает на script.Parent:WaitForChild('NonExistent').Something.
2026-06-08 13:00:51 +03:00
min
a1faf237a1 feat(lua): Этапы 6+7 — Sound + полная документация RUBLOX_LUA_API.md
Этап 6 — Sound:
  local s = Instance.new('Sound')
  s.SoundId = 'coin'  -- или 'jump'/'win'/'lose'/'hit'/'click'/'pickup'
  s.Volume = 1
  s.PlaybackSpeed = 1.2
  s:Play()
  s.Ended:Connect(function() print('ended') end)
SoundService:PlayLocalSound(sound) тоже работает.
Маппинг roblox-AssetID на встроенные звуки по эвристике (substring match).

Этап 7 — Документация:
RUBLOX_LUA_API.md — полный справочник всего реализованного.
Содержание: базовые типы, DataModel, Part-setters, Instance.new,
события (Touched/Heartbeat/RemoteEvent), таймеры, GUI, Sound,
TweenService, Humanoid, что не работает, готовый пример игры
(KillBrick + Coin + GUI-счётчик).

Этим завершается план RUBLOX_LUA_SUPPORT_PLAN (все 7 этапов).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-08 12:45:15 +03:00
min
371ddaaae8 feat(lua): Этап 5 — GUI (Frame, TextLabel, TextButton, ImageLabel, TextBox, ScrollingFrame)
В Lua теперь работает Roblox-style GUI:
  local sg = Instance.new('ScreenGui')
  local label = Instance.new('TextLabel', sg)
  label.Text = 'Hello'
  label.TextColor3 = Color3.fromRGB(255, 255, 0)
  label.Position = UDim2.new(0.5, 0, 0.5, 0)
  label.Size = UDim2.new(0.2, 0, 0.05, 0)

  local btn = Instance.new('TextButton', sg)
  btn.Text = 'Click me'
  btn.MouseButton1Click:Connect(function()
    print('clicked!')
  end)

Реализация: GUI-обёртка newGuiInstance создаёт элемент через gui.create
команду → GameRuntime.scene3d.guiManager. Setter'ы Text/Visible/
BackgroundColor3/TextColor3/TextSize/Position/Size шлют gui.update.
Destroy шлёт gui.remove. Клики через guiClick → guiByLocalRef →
inst.MouseButton1Click.Fire().

Добавлен localPlayer.PlayerGui для совместимости с Roblox-скриптами.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-08 12:40:49 +03:00
min
936f93a42c fix(lua): part.Position теперь реально двигает куб
КОРНЕВАЯ ПРИЧИНА: BabylonScene.freezeStaticPrimitives() замораживает
world matrix anchored-примитивов при Play для оптимизации.
mesh.position.set(x,y,z) после этого не обновляет рендер.

Фикс в PrimitiveManager.updateInstance: если patch содержит position/
rotation/size — расфризить world matrix прежде чем менять transform.
2026-06-08 12:19:14 +03:00
min
ecc2055b3d fix(lua): partSet применяется через PrimitiveManager.updateInstance (был applyPatch/update — их нет); очистка debug-логов 2026-06-08 12:00:29 +03:00
min
0d7224a2b8 fix(lua): WASM memory access — resume coroutine через lua.global.get вместо doStringSync
При каждом tick'е tickScheduler делал lua.doStringSync(resume code),
что вызывало re-entrant WASM-крах memory access out of bounds после
нескольких task.wait() итераций.

Фикс: кешируем ссылку на __rbxl_resume_co при init и зовём её напрямую.
Это безопасный путь (не парсит код заново, не открывает вложенный
Lua-state поверх существующего).
2026-06-08 11:50:22 +03:00
min
8ac2637615 feat(lua): Этап 4 — Part setters + task.wait + Instance.new + Destroy + TweenService
Этап 4.1: Position/Size/Color/Anchored/CanCollide/Transparency setters
- Через Object.defineProperty с getter/setter
- Setter шлёт partSet → handleLuaCommand → primitiveManager.applyPatch
- Формат payload соответствует rbxl-lua-integration

Этап 4.2: Instance.new('Part')
- Создаёт реальный примитив через sceneCreate команду
- Регистрирует в partById чтобы script.Parent.Touched работал
- Автоинкремент id с базы 100000

Этап 4.3: part:Destroy()
- sceneDelete → primitiveManager.removeInstance
- Также удаляет из Workspace.Children

Этап 4.4: task.wait(sec) через coroutine.yield
- Каждый скрипт стартует как coroutine
- task.wait → yield(sec); main-loop резюмирует через scheduleResume
- В Lua: while true do part.Position = ...; task.wait(0.1) end
  теперь работает корректно (raw80и не зависает UI)

Этап 4.5: BindableEvent + RemoteEvent
- Уже было в Instance.new (.Event = makeSignal()).
- Между Lua-скриптами работает через общий VM.

Этап 4.6: TweenService:Create
- Реальная интерполяция Vector3.Lerp / Color3.Lerp / number
- Через _stepTweens в tickScheduler каждый кадр
- tween.Completed signal фейерится по завершению

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-08 11:46:01 +03:00
min
2b15ec821a feat(lua): Этап 3 — DataModel + Touched + Humanoid (main-thread wasmoon)
Главное достижение: KillBrick работает.
script.Parent.Touched:Connect(fn) фейерится когда игрок касается куба,
humanoid:TakeDamage(100) → playerSet команда → BabylonScene.player.hp=0
→ respawn + playerDied event.

Архитектурные изменения:
- LuaSharedSandbox v3: wasmoon в MAIN потоке вместо Worker'а.
  DevTools видит точные ошибки, breakpoints работают,
  console.log в RobloxShim виден сразу.
- LuaSharedWorker.js удалён (больше не нужен).
- RobloxShim добавляет полное DataModel дерево:
  game / Workspace / Players / LocalPlayer / Character /
  Humanoid / HumanoidRootPart / 15 services (RunService.Heartbeat,
  TweenService, HttpService, DataStoreService, etc).
- newPart создаёт RbxPart-обёртку вокруг каждого primitive в сцене,
  Touched/TouchEnded signals.

Wasmoon-quirk:
- TypeError: Cannot read properties of null (reading 'then') возникает
  когда JS-функция возвращает null в Lua-контекст. PromiseTypeExtension
  делает .then без guard. Везде заменили null → undefined (push'ится как nil).
- _rbxl_get_part_by_id возвращает undefined если не нашёл, FindFirstChild и
  прочие тоже undefined вместо null.

GameRuntime.js:
- _buildSceneSnapshot теперь даёт id (для partById), color, anchored,
  canCollide, opacity полей у primitives.
- partSet/sceneCreate user-Lua → handleLuaCommand (rbxl интеграция).
- playerSet handler: humanoid.Health=0 → respawn + hpChange event.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-08 11:32:31 +03:00
min
b7a0b083b6 fix(lua): Vector3.Magnitude/Unit как getters + сохранение language в БД
Vector3:
- Magnitude теперь getter (без скобок) — как в Roblox
- Unit теперь getter
- Поддержаны lowercase алиасы magnitude, unit

Сохранение:
- BabylonScene serialize включает language в scripts[]
- Clip/copy включает language
- LuaSharedWorker.handleInit обёрнут в try/catch с детальной ошибкой
- LuaSharedWorker использует статический import для wasmoon

Этап 2 завершён полностью. Lua-runtime прошёл все тесты:
print, warn, Vector3, Color3, UDim2, CFrame, Enum, task.delay/spawn/defer,
RunService.Heartbeat, math/string/table, pcall.

Следующий этап 3: DataModel (game.Workspace + Instance + script.Parent +
Part.Touched + Part.Position setter).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-08 10:51:42 +03:00
min
06df77cc97 feat(lua): этапы 1+2 — Lua-скрипты в Рублоксе
Этап 1 (UI):
- Скрипт имеет поле language: 'js' | 'lua' (дефолт 'js')
- Переключатель JS / Lua в шапке ScriptEditor (жёлтый / синий)
- При смене с пустого/template — подставляется шаблон нового языка
- При смене с реальным кодом — confirm
- Monaco автоматически переключает подсветку
- Badge JS/LUA в HierarchyPanel рядом с именем скрипта

Этап 2 (базовый runtime):
- LuaSharedSandbox — обёртка с API совместимым с ScriptSandbox
- LuaSharedWorker — Web Worker с одним wasmoon-VM на всю игру
- RobloxShim — Vector3/Color3/UDim2/Vector2/CFrame, Enum.*, print/warn,
  wait/task.*, RbxSignal, Instance.new (база), game.GetService (стабы),
  RunService.Heartbeat
- Scheduler для task.delay/defer через main loop tick
- GameRuntime разделяет скрипты: JS / Roblox-Lua (импорт) / user-Lua

На Этапе 3 — DataModel (game.Workspace + Instance.Parent + Touched).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-08 09:57:12 +03:00