Начало работы

Установка на сервер

Чтобы игровой сервер запускал плагины amxts, на нём нужны две вещи: модуль amxts_amxx и папка addons/amxts с плагинами. На этой странице — как поставить их на свой сервер. Другой путь — сервер в Docker, в котором всё это уже есть.

Что нужно серверу

  • Counter-Strike 1.6 на HLDS, Windows или Linux. Рекомендуем ReHLDS.
  • Metamod и AMX Mod X 1.9 или новее с модулями самого AMX Mod X engine, fakemeta, hamsandwich, cstrike и fun. amxts проверяется на AMX Mod X 1.10 с Metamod-R.
  • ReGameDLL и ReAPI — для всех событий игры, которые есть только у ReGameDLL и ReHLDS, в том виде, в каком их поднимает игра, и для полей правил игры, которые добавляет ReGameDLL. Без них плагин пишется так же: свойства сущностей (игроки и сущности) и действия с игроком (give, respawn, …) работают через модули AMX Mod X fun, cstrike, hamsandwich и fakemeta, и большинство событий игры слышно через них же, некоторые — не целиком (сервер без ReAPI). Плагин спрашивает об этом через hasModule("reapi"). Проект для такого сервера пишет target: "hlds" в amxts.config.ts (include сервера), и обработчик события, которое там никто не слышит, не собирается.
  • Для плагинов .ts, которые компилирует сервер: 64-битная система — Windows x64 или Linux x86-64 с glibc 2.27 или новее. 32-битный hlds_linux работает на ней как есть. Серверу, который только запускает плагины, собранные в другом месте, это не нужно.
Оригинальный HLDS
На HLDS от Valve — Metamod и AMX Mod X, без ReHLDS, ReGameDLL и ReAPI; проверено на Linux с metamod-p — события, которые есть только у ReGameDLL и ReHLDS, слышны через собственные модули AMX Mod X, так, как их слышит там плагин на Pawn. Чего нет:
  • событий, которые там никто не слышит, — вопросов правил игры (fallDamage, canHaveItem, …), движения игрока (jumpMovement, move, …), собственных событий движка (printf, addResource, …), giveDefaultItems и взрывов гранат: обработчик такого события не вызывается никогда, и консоль сервера говорит об этом один раз, когда его добавляют;
  • того, чего не могут дать некоторые из слышных, — большинство приходит, когда игра уже сделала своё, и preventDefault() и запись поля там ничего не делают, а у некоторых нет какого-то поля: это перечислено в событиях игры, и просьба об этом — одна строка в консоли;
  • полей правил игры teamBalanced, neededPlayers, skipShowMenu, escapeRatio и updateInterval: они читаются как 0 и не записываются, о чём сказано один раз; timeLimit и gameStartTime считаются из mp_timelimit;
  • собственных нативов ReAPI (get_entvar, get_member, rg_*): вызов ничего не делает и отвечает 0, о чём сказано один раз для каждого натива.

Серверный набор

Набор — один архив на систему, в нём всё, что ставится на сервер:

системаархивмодуль
Windowsamxts-server-windows-x64.zipamxts_amxx.dll
Linuxamxts-server-linux-x64.tar.gzamxts_amxx_i386.so

Скачайте его из выпусков: той же версии, что @amxts/core в ваших проектах.

Что внутри — так, как оно ложится в папку игры (cstrike/):

addons/
├── amxmodx/
│   ├── modules/amxts_amxx.dll          на Linux — amxts_amxx_i386.so
│   └── scripting/include/amxts.inc     для плагинов на Pawn: поля, которые плагины добавляют Player
└── amxts/
    ├── plugins.ini                     список плагинов amxts: hello.ts
    ├── plugins/                        ваши плагины, а рядом с ними:
    │   ├── hello.ts                    плагин-пример
    │   ├── facade.ts, natives.ts, …    API, которым пользуется плагин
    │   ├── imports.d.ts                чем плагин пользуется без импорта, для редактора
    │   ├── tsconfig.json               для редактора, открытого на этой папке
    │   └── .assemblyscript/            типы, на которые указывает tsconfig.json
    ├── build/                          куда сервер компилирует плагины .ts
    └── tools/                          компилятор: amxts-compile, wamrc, natives.txt, licenses/
README.txt

tools/ — для своей системы: на Windows это amxts-compile.exe и wamrc.exe. Если при загрузке на Linux у файлов пропал бит исполнения — ничего страшного: модуль ставит его заново перед запуском.

Установка

  1. Скопируйте addons/ из набора поверх addons/ в папке игры.
  2. Добавьте модуль в addons/amxmodx/configs/modules.ini, рядом с reapi — или одной строкой на обычном HLDS:
    reapi
    amxts_amxx
    

    AMX Mod X находит amxts_amxx.dll или amxts_amxx_i386.so по этому имени. В plugins.ini строка не нужна: что нужно модулю, он загружает сам (плагин-хост).
  3. Запустите сервер или перезапустите, если он работает.

При первом запуске сервер компилирует пример и загружает его. В консоли:

[amxts] compiling .../addons/amxts/plugins/hello.ts
[amxts] compiler exited with 0
[amxts] loaded hello.ts

amxts_plugins в консоли сервера показывает плагины и что с каждым из них, и сколько обработчиков, которые модуль одалживает плагинам, — для команд, таймеров и событий игры, — занято:

[amxts] 1 plugin(s): 1 running, 0 unloaded, 0 refused; 2 of 512 callback slots in use
  hello.ts  running   Hello 1.0.0  by you - An example to edit

Зайдите на сервер и напишите в чат /hp — пример ответит.

Обновление с v0.2

Сервер, на который выкладывает проект, обновляется из проекта:

npx amxts upgrade

Вместе с пакетами и кодом проекта (upgrade) команда кладёт модуль нового выпуска в addons/amxmodx/modules/ — и компилятор в addons/amxts/tools/, если он есть на сервере, — оставляя каждый старый файл рядом с его версией (amxts_amxx.dll.0.1.0). Перезапустите сервер, чтобы загрузить новый модуль. Сервер без проекта берёт набор нового выпуска, как при установке.

Что пишет модуль

При каждом запуске модуль раскладывает addons/amxts: папки plugins, build и tools и файлы, с которыми он запускает плагины, — API ядра (facade.ts, natives.ts, constants.ts и остальные), imports.d.ts и tsconfig.json в plugins/, natives.txt в tools/. Их он переписывает каждый раз: они принадлежат модулю, и правка в них пропадёт.

hello.ts и plugins.ini (с hello.ts) он пишет, только когда их нет, и дальше не трогает: они ваши. Поэтому пример появится и на сервере, где есть только модуль, — но чтобы его скомпилировать, нужна tools/ из набора. Без неё консоль скажет amxts-compile is missing - a .ts plugin needs the compiler beside the module, и сервер будет запускать только плагины, собранные в другом месте.

Один набор — один модуль
Модуль и остальные файлы набора — из одной сборки. Новый модуль ставьте на сервер вместе с остальным его набором: компилятор или файл API из другой сборки делают плагины, которые не загрузятся. Компилятор другой сборки ничего не компилирует, а консоль называет обе сборки: .../plugins/hello.ts is not compiled: amxts-compile is 0.1.0+5f1c2a9e07, the module 0.2.0+1bf291c0ab - take both from the same release.

Плагин-хост с v0.2

До AMX Mod X — его нативов, его форвардов, нативов, которые регистрируют плагины на Pawn, — модуль дотягивается через свой плагин, amxts_host.amxx, который носит в себе. При каждом запуске он пишет этот плагин в addons/amxmodx/plugins/ и называет его в addons/amxmodx/configs/plugins-amxts.ini — списке, который AMX Mod X читает после plugins.ini; когда сервер останавливается, модуль удаляет оба. Поэтому хост загружается после плагинов на Pawn из plugins.ini, а amxx plugins показывает его среди них — все плагины amxts работают внутри него. Ни тот, ни другой файл не правят и никуда не копируют: они принадлежат модулю.

Плагины

addons/amxts/plugins.ini перечисляет плагины, которые запускает сервер, — по одному файлу из addons/amxts/plugins/ на строку, в порядке загрузки. Строка, которая начинается с ; или #, пропускается.

; One plugin per line, as a file in plugins/.
; A .ts is compiled by the server; a .aot is loaded as it is.
myplugin.aot
hello.ts
  • .aot — плагин, собранный в проекте; загружается как есть. Он собран под систему сервера: собранный для Windows на Linux не загрузится (система сервера).
  • .ts сервер компилирует в addons/amxts/build/<имя>.aot и компилирует снова, только когда исходник новее или когда сборка там сделана другой версией amxts.
Плагин собран под одну версию amxts
.aot помнит, какой версией amxts он собран, и модуль загружает только плагины, собранные под него самого: плагин другого выпуска обращался бы к модулю так, как тот уже не принимает. Такой плагин не загружается, остальные загружаются, а консоль говорит, какой собрать заново: [amxts] myplugin.aot was built for amxts 0.1.0, this is 0.2.0 - build it again (или was built for an older amxts). Обновив модуль, соберите проект заново и выложите его (npx amxts build --deploy); .ts на сервере перекомпилируется сам.

Из проекта

Проект выкладывается в папку addons/amxts сервера, которую называет AMXTS_SERVER в .env проекта:

AMXTS_SERVER=D:/hlds/cstrike/addons/amxts

Подойдёт и папка самого сервера (D:/hlds), его cstrike или cstrike/addons: сборка берёт cstrike/addons/amxts внутри неё и называет выбранную папку в строке Server своего заголовка. Папка, которая не подходит ни под один вариант, останавливает сборку одной строкой о том, где она искала.

npx amxts build --deploy копирует собранные .aot в addons/amxts/plugins/ и пишет addons/amxts/plugins.ini: сначала модули, потом плагины проекта, а после них — все строки, которых сборка не знает. Include плагина, который экспортирует нативы, тоже копируется — в addons/amxmodx/scripting/include/, для плагинов на Pawn, которые компилируются на сервере. npx amxts dev делает это при каждом сохранении и перезагружает сервер через rcon (горячая перезагрузка).

Написанные на сервере

Файлу .ts проект не нужен: положите его в addons/amxts/plugins/, впишите в plugins.ini и загрузите через amxts_reload или со следующей картой. Дальше каждое сохранение снова компилирует и перезагружает его. Ошибка компиляции идёт в консоль сервера и в addons/amxts/build/compile.log; за плагином, который не собрался, тоже следят, так что загружает его сохранение исправления.

Такой плагин пользуется тем, что лежит в его папке: API ядра — без импорта, как в проекте (автоимпорты), а @amxts/core/natives, @amxts/core/constants, @amxts/core/fs и вашими собственными файлами — через импорт. Пакет модуля, например @amxts/menu-core, — для плагинов, собранных в проекте. В редакторе открывайте саму addons/amxts/plugins, а не корень сервера: её tsconfig.json и говорит редактору о типах.

Компиляция задерживает сервер
Пока сервер компилирует плагин .ts, он ждёт — секунду-две. При смене карты этого никто не заметит; посреди раунда игра на это время замрёт. На сервер, где играют, выкладывайте .aot, собранные в проекте.

Перезагрузка

Модуль проверяет плагины десять раз в секунду. .aot, записанный заново после загрузки, или .ts, сохранённый и скомпилированный без ошибок, перезапускает все плагины amxts с диска — без смены карты и без команды. amxts_reload делает то же вручную. Перезапуск заново читает plugins.ini, так что плагин, добавленный в список, загружается со следующим.

Один плагин с v0.2

amxts_unload shop       // останавливает shop.ts
amxts_load shop         // запускает его снова
amxts_reload shop       // перезапускает с диска, перекомпилировав, если его .ts изменился
amxts_load arena.ts     // файл из plugins/, которого нет в списке, — до смены карты

Плагин называют его строкой в plugins.ini, с .ts или .aot или без них. amxts_unload останавливает его и забирает всё, что он зарегистрировал, — таймеры, команды, события игры, обработчики меню и слушателей сообщений, — и плагин остаётся остановленным до amxts_load или следующей карты; перезапуск всех плагинов тоже его не запускает. amxts_reload <плагин> перезапускает только этот плагин, остальные работают дальше.

Плагин, чьим общим модулем пользуются другие плагины, держит то, что они через него сделали, — меню, функцию, которую ему передали. Поэтому amxts_unload отказывает, пока работает хоть один из них, и называет их: сначала выгрузите их. amxts_reload такого плагина перезапускает их после него.

amxts_plugins показывает каждый плагин как running (работает), unloaded (выгружен) или refused (отвергнут) с причиной: не компилируется, собран для другой версии amxts или другой системы, его верхний уровень упал.

Плагин начинает заново
Загруженный снова плагин начинает со своего верхнего уровня: то, что он держал в переменных, пропадает. То, что должно его пережить, кладите в общие поля игрока или в Storage.

Команды сервера

командачто делает
amxts_pluginsсписок плагинов: файл, состояние (running, unloaded, refused и почему), имя, версия, автор; и сколько слотов обработчиков занято
amxts_reloadзаново читает plugins.ini и перезапускает все плагины amxts с диска
amxts_reload <плагин>перезапускает один плагин с диска и плагины, которые пользуются его модулем
amxts_unload <плагин>останавливает плагин и то, что он зарегистрировал, до amxts_load или следующей карты
amxts_load <плагин>запускает остановленный плагин или плагин из plugins/, которого нет в списке
amxts_traceпишет в лог каждый вызов плагина — чтобы найти, что роняет сервер; повторный вызов выключает

Другой список плагинов

+localinfo amxts_plugins <файл> в командной строке сервера даёт модулю другой список — путь от папки игры. Его плагины — файлы в plugins/ рядом с этим списком, а .ts среди них компилируется в build/ рядом с ним:

hlds.exe -game cstrike +localinfo amxts_plugins addons/amxts/myserver/plugins.ini +map de_dust2

Со своим списком модуль не раскладывает addons/amxts: он запускает этот список, а остальную установку оставляет как есть. Так сервер в Docker запускает dist/ проекта.