7 Commits

Author SHA1 Message Date
min
b09dd703af feat(rbxl): GUI mode + предупреждение про большие карты
Robloxity (20402 Part, 278 скриптов, 295 BillboardGui, 0.1 FPS) показал:
1. Большие карты могут зависнуть студию навсегда.
2. BillboardGui/SurfaceGui (вывески, табло) рендерятся в 3D-сцене и
   при 200+ штук убивают FPS.

Фиксы:

1. Предупреждение в модалке если parts > 5000 (жёлтое) или > 15000
   (красное "может зависнуть"). Подсказка про режимы.

2. Новая опция guiMode (показывается если GUI > 50 элементов):
   - 'all' — все, как было.
   - 'screen-only' (рекомендуется) — только ScreenGui HUD,
     BillboardGui/SurfaceGui удаляются.
   - 'skip' — без GUI совсем.

3. converter.py: маркирует элемент полем gui_container_kind:
   'screen' / 'billboard' / 'surface'.

4. app.py: _apply_gui_mode() фильтрует scene.gui[] по режиму.

Deploy app.py + converter.py на VM 130.

Robloxity рекомендуем импортировать со screen-only — Карта Robloxity
будет работать в 5-10× быстрее без вывесок города.
2026-06-08 21:38:08 +03:00
min
08817925b5 fix(import): spawn point выше пола + auto-fallback если SpawnLocation нет
Юзер: "персонаж в стене заспавнился, ходить не может".

Проблема: SpawnLocation в старых .rbxl ставится по CFrame с минимальным
отступом от пола. Наш +1.5 недостаточно — толстые Floor'ы 2-3 units
high полностью утопляют персонажа. Anchored=True (наш фикс) не даёт
выпрыгнуть.

Фиксы:
1. SpawnLocation +1.5 → +5 единиц выше плиты.
2. Auto-fallback: если spawnPoint остался дефолтом (0,2,0) = в карте
   не было SpawnLocation вообще — ставим над самой высокой Part:
   y = max(part.y + part.sy/2) + 5. Игрок упадёт на крышу/верх.

Deploy converter.py на VM 130. Юзер должен переимпортировать карту
чтобы получить новый spawnPoint.
2026-06-08 21:05:15 +03:00
min
913283ffa6 feat(rbxl): 9 механик ROBLOX Battle (Teams/Leaderstats/HUD/Tools/etc)
Реализовано из 14 механик:

1. Teams (game.Teams, Player.Team, TeamColor): scene.teams[] из конвертера,
   эвристика TeamBeacon-Model → автоматически создаются 4 команды.
   В shim создаются Team-инстансы при snapshot, авто-эквип игрока в первую.

2. Leaderstats UI: IntValue.Value реактивно шлёт leaderstatSet → существующий
   LeaderstatsManager (define + set). HUD автоматически рисуется в правом
   верхнем по родительскому Name='leaderstats'.

3. BindableFunction + RemoteFunction + Message/Hint класс. Message с
   реактивным .Text и .Parent шлёт hudMessage в наш RbxlHudOverlay.

4. KillFeed UI + creator-tag tracking. RbxlHudOverlay.addKillFeed() рисует
   А → [weapon] → Б в правом верхнем. Humanoid.TakeDamage при Health=0
   ищет creator-ObjectValue и шлёт killFeed. Авто-respawn через 2с.

5. SpawnLocation.TeamColor → scene.team_spawns[] для будущей логики
   команд-спавна.

6. Tool:Clone() / Model:Clone() / :clone(): поверхностный клон + lowercase
   alias. Также :MakeJoints/:BreakJoints/:Remove/:remove no-op методы.

7. Creator-tag handling в TakeDamage (см. пункт 4).

12. Bouncer/батут: BodyVelocity с +Y и Parent=Torso/HumanoidRootPart →
    эвристика "толкаем вверх" → playerSet jumpVelocity → реальный jump
    через player._vy.

14. Mouse.Icon → CSS cursor на canvas (crosshair для не-пустых).

Также:
- RbxlHudOverlay.js — новый модуль DOM-оверлей для HUD-элементов
  (KillFeed/Message/WinGui). Lazy-создаётся при первом hudMessage/killFeed.
- BabylonScene.serialize включает scene.teams и scene.team_spawns.
- Converter: scene = teams[] + team_spawns[]. TeamBeacon Model'и → команды.
- Deploy converter.py на VM 130.

Остались: 8 Regeneration, 9 BattleArmor, 10 WinGui/FireButton кастомное
позиционирование, 11 AdminConsole (no-op уже ok), 13 NotLinkedBlocker.
2026-06-08 19:43:36 +03:00
min
5b44a286a9 fix(import): заливка теней работает + Anchored=True для всех импорт. Part
1. PrimitiveManager: mat.ambientColor=(1,1,1). Теперь scene.ambientColor
   ("Заливка теней" слайдер) реально влияет на тени. Юзер крутит
   значение и видит изменение.

2. converter.py: Roblox-Part импортируется всегда с Anchored=True
   (force-anchored). Welds у нас заглушки, без них unanchored Part'ы
   рассыпаются физикой. Если юзеру нужно падающее — снимет в
   инспекторе вручную.

Деплой converter.py на VM 130 + systemctl restart.
2026-06-08 18:59:23 +03:00
min
3a82b3c64d fix(import): расширил BrickColor палитру + убрал ambient material
Главная причина пересвета:
1. BrickColor 151 (Earth green = трава Crossroads) ОТСУТСТВОВАЛ
   в таблице. Пол получал дефолт #cccccc и выглядел белым.
   После анализа карты 344 примитива использовали дефолт.
2. mat.ambientColor=(1,1,1) + scene.ambientColor=(0.3) делало белые
   цвета пересветлёнными — серый выглядел белым.

Фикс:
- BRICKCOLOR_TO_HEX расширен с ~50 до ~120 цветов. Добавлены:
  151 (Earth green), 26 темный, 18, 115-148, 168-301, 1021-1032 и др.
  После: #cccccc дефолт 344→68 (бОльшая часть теперь правильных).
- Убран mat.ambientColor — оставлен default (0,0,0). Lambert чистый:
  освещённая грань = diffuse, тень = почти чёрная (scene.ambient смягчает).
  Цвета теперь точно как в diffuse, без пересвета.

Деплой: converter.py скопирован на VM 130 + systemctl restart.
2026-06-08 17:00:25 +03:00
min
0b677529e1 feat(rbxl-importer): поддержка XML-формата .rbxl (старые карты до 2010)
All checks were successful
CI / Lint (pull_request) Successful in 1m7s
CI / Build (pull_request) Successful in 1m57s
CI / Secret scan (pull_request) Successful in 23s
CI / PR size check (pull_request) Successful in 7s
CI / Deploy to S1 + S2 (pull_request) Has been skipped
Старые Roblox-карты (Crossroads, ROBLOX Battle, и др. из эры 2007-2010)
сохранены в XML-формате (<roblox version=4>... вместо binary <roblox!...).
Наш парсер падал на 'missing <roblox! magic'.

Новое:
- rbxl_xml_parser.py: парсит XML-формат через стандартный xml.etree.
  Поддерживает все типичные property-теги: string, bool, int, float,
  Vector3, Vector2, CoordinateFrame, Color3, Color3uint8, BrickColor,
  Ref, BinaryString, UDim/UDim2, PhysicalProperties, OptionalCFrame.
- В _parse_property: <int name=BrickColor> заворачивается в BrickColor
  объект — converter ожидает .code атрибут.
- Алиасы PascalCase: name→Name, size→Size, shape→Shape (старый XML
  использовал camelCase с маленькой первой буквой).

app.py:
- /analyze: авто-детект XML vs Binary по magic bytes. Если XML —
  используем parse_xml(), иначе старый parse().

Тест на arch1_Original_Crossroads.rbxl: 877 instances, 777 Part,
83 Model — конвертится в 777 примитивов без warnings.
2026-06-08 16:23:18 +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