Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RustCore — Rust-диспетчер для Garry's Mod

Центральный модуль, который первым получает игровые события (через hook.Add на Lua-стороне) и раздаёт их дальше зарегистрированным аддонам через RustCore.RegisterHook. Плюс — очередь для тяжёлых асинхронных задач в отдельных потоках, с безопасным возвратом результата в главный/Lua поток.

Требования

  • Rust nightly (крейт gmod этого требует):
    rustup toolchain install nightly
    rustup override set nightly   # внутри папки проекта — rust-toolchain.toml это уже форсирует
    
  • Кросс-компиляция под нужные таргеты (см. таблицу ниже):
    rustup target add i686-pc-windows-msvc
    rustup target add x86_64-pc-windows-msvc
    rustup target add i686-unknown-linux-gnu
    rustup target add x86_64-unknown-linux-gnu
    
    Для сборки Windows-таргетов с Linux/macOS понадобится cargo-xwin или cross — нативный MSVC-линкер кросс-компиляцией "из коробки" не собирается. Проще всего собирать _win* таргеты прямо на Windows, а _linux* — на Linux (или через cross в Docker).

Именование файлов (важно!)

GMod ищет модули по строгому шаблону <gmXX>_<name>_<platform>.<ext>:

Сборка Платформа Итоговое имя файла Rust target
Сервер Windows x64 gmsv_rustcore_win64.dll x86_64-pc-windows-msvc
Сервер Linux x64 gmsv_rustcore_linux64.dll x86_64-unknown-linux-gnu *
Клиент Windows x86 gmcl_rustcore_win32.dll i686-pc-windows-msvc
Клиент Windows x64 gmcl_rustcore_win64.dll x86_64-pc-windows-msvc
Клиент Linux x64 gmcl_rustcore_linux64.dll x86_64-unknown-linux-gnu *

* GMod на Linux исторически ждёт файл с расширением .dll (не .so) даже для линуксовой сборки — просто переименуй собранный .so в .dll.

GMod сейчас постепенно переезжает на 64-битную ветку (x86-64 branch) — если таргетишь именно её, и сервер, и клиент 64-битные на обеих ОС. Легаси-ветка (по умолчанию у многих серверов) — клиент 32-бит на Windows. Собери сразу несколько вариантов, если не уверен, на какой ветке будут игроки.

Сборка

# из папки rustcore/
cargo +nightly build --release --target x86_64-unknown-linux-gnu
cargo +nightly build --release --target x86_64-pc-windows-msvc
# и т.д. под нужные таргеты

Собранный файл лежит в:

  • Windows: target/<TARGET>/release/rustcore.dll
  • Linux: target/<TARGET>/release/librustcore.so

Переименуй согласно таблице выше (убери префикс lib, поставь gmsv_/gmcl_, поставь .dll) и положи в:

garrysmod/lua/bin/

Установка Lua-части

Скопируй содержимое lua_addon/lua/ в garrysmod/lua/ (или сразу в аддон в garrysmod/addons/rustcore/lua/):

addons/rustcore/lua/autorun/rustcore_init.lua   -- обязательно
addons/rustcore/lua/example_addon/example.lua   -- пример, можно удалить
addons/rustcore/lua/bin/gmsv_rustcore_*.dll     -- сюда же бинарники (или в lua/bin/ отдельно)

Проверка

При старте сервера/клиента в консоли должно появиться:

[RustCore] модуль загружен
[RustCore] диспетчер запущен

Дальше любой другой аддон подключается так:

-- priority: больше = раньше вызывается, обычным хукам достаточно 0
RustCore.RegisterHook("Think", "my_addon", 0, function()
    -- ...
end)

API

Функция Назначение
RustCore.RegisterHook(event, owner, priority, fn) Подписать fn на событие. Выше priority — раньше вызов.
RustCore.RemoveHook(event, owner) Снять хук(и) владельца с конкретного события.
RustCore.RemoveAllHooks(owner) Снять вообще все хуки владельца (на выгрузке аддона).
RustCore.Dispatch(event, ...) Точка входа — вызывается из hook.Add на стороне GMod.
RustCore.HookCount(event) Сколько обработчиков подписано.
RustCore.SetSlowHookThreshold(ms) С какого времени выполнения хук считается "медленным" и логируется (по умолчанию 2 мс).
RustCore.StartTask(kind, payload, callback) Запустить асинхронную задачу типа kind в отдельном потоке. callback(ok, data).
RustCore.PollTasks() Забрать готовые результаты асинхронных задач — дёргать регулярно (на Think).

Как добавить свой тип асинхронной задачи

Задачи регистрируются на стороне Rust, не Lua — это осознанное ограничение: задача выполняется в отдельном потоке и должна быть чистым нативным кодом (без обращения к lua_State). Добавляется в gmod13_open (src/lib.rs):

tasks::register_task_kind("my_kind", |payload| {
    // тяжёлая работа: парсинг, сеть, крипто, что угодно
    Ok(format!("результат для {}", payload))
});

Дальше из Lua: RustCore.StartTask("my_kind", "данные", function(ok, data) ... end).

Профилирование медленных хуков

RustCore.Dispatch сам замеряет время каждого вызванного обработчика и, если оно превышает порог (RustCore.SetSlowHookThreshold, по умолчанию 2 мс), печатает в консоль что-то вроде:

[RustCore] МЕДЛЕННЫЙ ХУК: 'Think' владельца 'example_addon' занял 4.13 мс

Так сразу видно, чей код тормозит, без стороннего профилировщика.

Что дальше стоит доделать

  • Реальные обработчики задач под конкретные сценарии (сейчас есть только пример "echo" в gmod13_open).
  • Если появится общий event bus между сервером и клиентом — сериализация payload (сейчас предполагается строка/JSON, serde_json уже в зависимостях).

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages