Core

Forwards: events for other plugins

A forward is an event one plugin raises and other plugins hear - TypeScript and Pawn alike. It is how a plugin tells the rest of the server that a round of its game mode started, that a player bought something, that a setting changed.

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

The type parameters are the forward's arguments, up to 32 - as many as AMX Mod X gives a forward: new Forward("myplugin_on_start") has none, new Forward<Player, string> two. emit passes them to everyone who listens; it returns true when the forward went out.

A Pawn plugin hears it as any forward, with a public function of that name:

public myplugin_on_bought(id, const item[])
{
    client_print(id, print_chat, "You bought %s", item);
}

Listening from TypeScript

const 
bought
= new
Forward
<Player, string>("myplugin_on_bought");
bought
.
subscribe
((
player
,
item
) => {
console
.
log
(`${
player
.
name
} bought ${
item
}`); // player: Player, item: string
});
bought
.
subscribe
(onBought);
bought
.
unsubscribe
(onBought);
function onBought(
player
: Player) { // may take fewer parameters than the forward
console
.
log
(`${
player
.
name
} bought something`);
}

Another plugin makes a Forward of the same name and types and subscribes to it. The handler's parameters take the forward's types, so an arrow needs no annotations, and a handler of the wrong type is an error in the editor. A plugin may also subscribe to a forward it raises itself.

A forward raised by a TypeScript plugin reaches every subscriber. A forward a Pawn plugin raises reaches TypeScript when it is declared in an include amxts comes with - AMX Mod X's, ReAPI's and those of the modules amxts supports.

Argument types

Type parameterWhat Pawn gets
numbera whole number
boolean1 or 0
stringa string
Playerthe player's index; a subscriber gets the Player
Teamits TeamName number: "UNASSIGNED" 0, "TERRORIST" 1, "CT" 2, "SPECTATOR" 3
RoundWinnerits WinStatus number: "none" 0, "CT" 1, "TERRORIST" 2, "draw" 3
Float, or number where the include says Float:a Float
number[]an array; of Floats where the include says Float:
Vectoran array of three Floats

Team and RoundWinner need the forward's declaration in an include: the plugin's own (plugin({ include })) or one the build knows. The build reads how each argument crosses from it:

// in myplugin.inc: forward myplugin_on_joined(id, TeamName:team);
const 
joined
= new
Forward
<Player, Team>("myplugin_on_joined");
joined
.
emit
(player, "CT"); // Pawn gets (id, 2)
joined
.
subscribe
((
player
,
team
) =>
console
.
log
(`${
player
.
name
}: ${
team
}`)); // team: "CT"

The build stops, with the place and the reason, when:

  • a Team or a RoundWinner has no declaration to say which number it is;
  • a RoundWinner is declared as something other than WinStatus:;
  • a string is declared as a number (TeamName:team);
  • an array is declared as a number;
  • an array is declared without a tag (const data[3]): Pawn passes that as text - tag it, Float:data[3];
  • the declaration has another number of arguments.

A forward no include declares crosses as its types say.

An array from Pawn
Pawn passes an array without its size. An array in a forward a Pawn plugin raises reaches a subscriber whole when the include gives the size (Float:origin[3]); an array without one arrives empty.

When the forward is made

The forward is made on its first emit, or earlier with create(). AMX Mod X finds the Pawn plugins that hear a forward when it is made, so emit it no earlier than when every plugin has loaded - in the "pluginsLoaded" event or later. Subscribing does not make it.

Stopping

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

With "handled", the first Pawn handler that returns PLUGIN_HANDLED stops the forward: the handlers after it do not hear it. The default is "never": everyone hears it. Set it before the first emit.