Основы

Форварды: события для других плагинов

Форвард — событие, которое один плагин поднимает, а другие слышат, и на TypeScript, и на Pawn. Так плагин сообщает остальному серверу, что начался раунд его режима, что игрок что-то купил, что изменилась настройка.

const 
bought
= new
Forward
<Player, string>("myplugin_on_bought");
server
.
addCommand
("/buy <item>", ({
player
,
item
}) => {
bought
.
emit
(
player
,
item
);
});

Параметры типа — аргументы форварда, до 32 — столько, сколько AMX Mod X даёт форварду: new Forward("myplugin_on_start") без аргументов, new Forward<Player, string> — с двумя. emit передаёт их всем, кто слушает, и возвращает true, если форвард ушёл.

Плагин на Pawn слышит его как любой форвард — публичной функцией с этим именем:

public myplugin_on_bought(id, const item[])
{
    client_print(id, print_chat, "Ты купил %s", item);
}

Подписка из TypeScript

const 
bought
= new
Forward
<Player, string>("myplugin_on_bought");
bought
.
subscribe
((
player
,
item
) => {
console
.
log
(`${
player
.
name
} купил ${
item
}`); // player: Player, item: string
});
bought
.
subscribe
(onBought);
bought
.
unsubscribe
(onBought);
function onBought(
player
: Player) { // параметров может быть меньше, чем у форварда
console
.
log
(`${
player
.
name
} что-то купил`);
}

Другой плагин создаёт Forward с тем же именем и типами и подписывается на него. Параметры обработчика получают типы форварда, поэтому стрелке аннотации не нужны, а обработчик не того типа — ошибка в редакторе. Плагин может подписаться и на форвард, который поднимает сам.

Форвард, поднятый плагином на TypeScript, доходит до всех подписчиков. Форвард, который поднимает плагин на Pawn, доходит до TypeScript, если он объявлен в include, который идёт с amxts, — из AMX Mod X, ReAPI и модулей, которые поддерживает amxts.

Типы аргументов

Параметр типаЧто получает Pawn
numberцелое число
boolean1 или 0
stringстроку
Playerиндекс игрока; подписчик получает Player
Teamномер TeamName: "UNASSIGNED" 0, "TERRORIST" 1, "CT" 2, "SPECTATOR" 3
RoundWinnerномер WinStatus: "none" 0, "CT" 1, "TERRORIST" 2, "draw" 3
Float или number, где include пишет Float:Float
number[]массив; из Float, где include пишет Float:
Vectorмассив из трёх Float

Для Team и RoundWinner нужно объявление форварда в include: собственном include плагина (plugin({ include })) или в одном из тех, что знает сборка. Сборка читает из него, как передаётся каждый аргумент:

// в myplugin.inc: forward myplugin_on_joined(id, TeamName:team);
const 
joined
= new
Forward
<Player, Team>("myplugin_on_joined");
joined
.
emit
(player, "CT"); // Pawn получит (id, 2)
joined
.
subscribe
((
player
,
team
) =>
console
.
log
(`${
player
.
name
}: ${
team
}`)); // team: "CT"

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

  • у Team или RoundWinner нет объявления, которое сказало бы, какой это номер;
  • RoundWinner объявлен не как WinStatus:;
  • string объявлена числом (TeamName:team);
  • массив объявлен числом;
  • массив объявлен без тега (const data[3]): Pawn передаёт такой как текст — дайте ему тег, Float:data[3];
  • в объявлении другое число аргументов.

Форвард, которого нет ни в одном include, передаётся так, как говорят его типы.

Массив из Pawn
Pawn передаёт массив без его размера. Массив в форварде, который поднимает плагин на Pawn, доходит до подписчика целиком, если include указывает размер (Float:origin[3]); массив без размера приходит пустым.

Когда форвард создаётся

Форвард создаётся при первом emit или раньше, через create(). Плагины на Pawn, которые его слушают, AMX Mod X находит в момент создания, поэтому поднимайте его не раньше, чем загрузятся все плагины, — в событии "pluginsLoaded" или позже. Подписка форвард не создаёт.

Остановка

const 
vote
= new
Forward
<Player>("myplugin_vote");
vote
.
stopWhen
= "handled";

С "handled" первый обработчик на Pawn, который вернёт PLUGIN_HANDLED, останавливает форвард: обработчики после него его не слышат. По умолчанию — "never": слышат все. Задайте это до первого emit.