Commit graph

7 commits

Author SHA1 Message Date
f41bfde690 Lua: поля ENT-скриптов и модель-представитель для спавн-меню 2026-10-24 13:33:34 +03:00
300a6c6d98 Lua: Rust-API к реестрам list/weapons (list_names, call_weapon_method, weapon_string)
Some checks are pending
CI / checks (push) Waiting to run
2026-10-24 13:01:27 +03:00
087d57b582 Lua GMod: библиотеки list/weapons/scripted_ents и загрузка скриптов
Some checks are pending
CI / checks (push) Waiting to run
- библиотека `list` (Set/Add/Get/GetEntry/HasEntry) — реестры GMod, на них
  держатся списки оружия, энтити и спавна;
- `weapons.Register/Get/GetStored` и `scripted_ents.Register/Get`, запись в
  `list.Get("Weapon")` и `list.Get("SpawnableEntities")`;
- загрузчик `LuaRuntime::load_scripts(game_dir)`: выполняет `lua/weapons/*.lua`
  (со свежей `SWEP`, заранее созданными `Primary`/`Secondary`) и
  `lua/entities/*.lua` (с `ENT`), ошибка одного файла не роняет остальные;
  размер файла ограничен 1 МиБ;
- заглушки, без которых скрипты не запускаются: AddCSLuaFile, Model, Sound,
  include, DEFINE_BASECLASS, Material, game.AddParticles; GMod-синтаксис
  проходит через препроцессор (`!` → `not`);
- клиент загружает скрипты при старте: на настоящих ассетах — 3 оружия
  (fists/flechettegun/medkit), 5 энтити; `weapons.Get('weapon_fists')` читает
  Primary.ClipSize и ViewModel.

Тест `real_gmod_weapons_and_entities_load` (пропускается без ассетов).
Осталось: `continue` в препроцессоре (ломает widget_bones), include базовых
классов, привязка SWEP к вьюмодели и Q-меню.

26 сьютов зелёные.
2026-10-24 12:12:29 +03:00
aa7558721a lua: стандартная библиотека GMod — hook.Run, math, game, file с песочницей
Батч 3, шаг 3. Сначала измерено, а не придумано: прогнаны 130 файлов
gamemodes/sandbox, извлечены 182 различных вызова API с частотами.
Топ по частоте: hook.Run (63), math.Clamp (61), game.SinglePlayer (36),
math.Rand (27), render.AddBeam (21). Первые четыре — чисто Lua-слой,
сделаны здесь; render.* — отдельная большая работа.

hook.Run не синоним hook.Call: он останавливается на первом не-nil. На этом
построены все проверки Sandbox, подмена Run на Call ломала бы их молча.

Найдено три дефекта, все — измерением:

1. Ключи хуков — строки (идентификаторы скриптов), а не числа. Отбор только
   целочисленных ключей давал пустой список: хуки не выполнялись вообще,
   hook.Run возвращал nil.
2. Vec<Value> реализует IntoLua как таблицу, поэтому Function::call передавал
   хуку ОДИН аргумент вместо трёх — молча, без ошибки. Проверено:
   select('#', ...) внутри хука давал 1 при трёх переданных. То же с одиночным
   числом. Лечится Variadic; отдельный тест фиксирует именно эту ошибку.
3. math.Rand определён на Lua, а не на Rust: он зовёт math.random того же
   состояния и передаёт аргументы нативно.

file.* — с песочницей на garrysmod/: выход за корень это отказ, а не
предупреждение, абсолютные пути не даны, чтение ограничено 8 МБ. На живом
клиенте file.Read('../../../../etc/passwd') вернул nil.

Совпадения с GMod зафиксированы тестами: math.Round(-2.5) = -3,
math.Rand(x) даёт целое в [1, x], AngleDifference(10, 370) = 0,
Remap на вырожденном диапазоне даёт out_min, а не NaN.

Тестов 38 в glua (было 24), 23 набора по воркспейсу, clippy чист.
2026-10-13 13:17:28 +03:00
b991cc59f1 lua: мост к движку — Entity(), ents.* работают с живым миром
Батч 3, шаг 2. Крейт glua не зависит от engine: поведение отдаётся через
трейт Host, реализация которого живёт в клиенте. Иначе был бы цикл
зависимостей и Lua-слой нельзя было бы тестировать в одиночку.

Мир переведён в Rc<RefCell<World>> — скрипт обращается к нему из хуков в
любой момент. Все обращения через try_borrow: пересечение заимствований
даёт panic, а падать из-за скрипта клиент не должен.

Проверено измерением на gm_construct: ents.GetAll() возвращает 1227
сущностей, ents.GetByClass('prop_physics') читает позицию.

Найден и исправлен рассинхрон: move_prop обновлял позу экземпляра пропа,
но не запись в пуле сущностей. Lua читал z = -64, пока физика уже опустила
проп на z = -84 — «данные» и «картинка» разошлись, и заметить это можно
было только глазами. Теперь поза пишется в оба места всегда, даже без
модели: проп без модели всё равно стоит правильно, он просто не рисуется.
Возвращаемое значение move_prop теперь означает именно «геометрия
пересчитана».

После правки Lua читает z = -84.15848, физика даёт -84.15847778320313 —
совпадение до последнего бита.

Тест на паникующий хост: скрипт получает «невалидно» вместо падения.

Тестов 24 в glua, 56 в engine, 23 набора по воркспейсу, clippy чист.
2026-10-13 12:57:01 +03:00
b9b03abe3b lua: типы GMod — Vector, Angle, Color с арифметикой
Батч 3, шаг 1. Фундамент Lua-API: без этих типов Entity:GetPos() не
возвращает ничего, с чем можно считать.

Проверено тестами через настоящий LuaRuntime, а не голый интерпретатор:
скрипт считает теми же глобалами, что и обычный автор в Sandbox.

Решения по совместимости:
- пропущенные аргументы не бывают ошибкой: Vector() и Vector(1, 2) должны
  работать, иначе ломается бытовой код Sandbox;
- деление на ноль даёт 1, а не inf — inf в позиции пропа отравляет всю
  геометрию объекта;
- NaN из скрипта не доезжает до физики;
- компоненты цвета обрезаются в 0..255, а не отвергаются;
- Source — левая система координат: нулевые углы смотрят вдоль +X,
  yaw=90 — вдоль +Y.

Найден дефект чтения чисел в mlua 0.11: Value::as_number() различает только
Number и молча возвращает None на Integer, а LuaJIT отдаёт целые как
Integer. Vector(1, 2, 3) давал Vector(0, 0, 0) — и это выглядело как
«арифметика не работает». Собственный value_number() принимает Number,
Integer и строку-число.

Ещё убрат шум тригонометрии: cos(90°) в f32 равен 6.1e-17, и
Angle(0,90,0):Forward() печатал -0.00000004371139 вместо 0.

Тестов 17 в glua (было 1), 23 набора по воркспейсу, clippy чист.
2026-10-13 12:48:50 +03:00
2c13062b03 lua: рантайм LuaJIT с GMod-подобным API и автозагрузкой клиентских аддонов
- glua: print/Msg, hook.Add/Remove/Call, timer.Simple, concommand.Add,
  CreateConVar/CreateClientConVar/GetConVar, util/engine/game заглушки, FCVAR_*
- препроцессор GMod-синтаксиса: ! → not, != → ~=, && → and, || → or
  (вне строк/комментариев) — оригинальные клиентские скрипты GMod грузятся
- client: команда lua run/list, автозагрузка lua/autorun/client/*.lua из VFS,
  Think-хук и таймеры каждый кадр, вывод в HUD-лог
- fs: VirtualFs::list(prefix) для перечисления файлов (VPK/Pak/каталоги)
2026-10-12 04:29:09 +03:00