Центральный модуль, который первым получает игровые события (через hook.Add
на Lua-стороне) и раздаёт их дальше зарегистрированным аддонам через
RustCore.RegisterHook. Плюс — очередь для тяжёлых асинхронных задач в
отдельных потоках, с безопасным возвратом результата в главный/Lua поток.
- Rust nightly (крейт
gmodэтого требует):rustup toolchain install nightly rustup override set nightly # внутри папки проекта — rust-toolchain.toml это уже форсирует - Кросс-компиляция под нужные таргеты (см. таблицу ниже):
Для сборки Windows-таргетов с Linux/macOS понадобится
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-gnucargo-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_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)| Функция | Назначение |
|---|---|
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уже в зависимостях).