Broadcasting - Grisgram/gml-raptor GitHub Wiki

The Broadcasting subsystem in raptor consists of three main components:

Class Description
Sender This is your main object.
The Sender is kind of a radio-station, sending out broadcasts to all listening receivers.
Just create a new Sender() and add receivers to it.
NOTE: gml-raptor creates one Sender in the GAMECONTROLLER object. It can be accessed through the BROADCASTER macro. This macro will always point to a valid Sender.
Receiver When using the add_receiver function of your sender, a receiver is built with the given name, message_filter and callback.
The callback will receive one parameter, a Broadcast instance.
It offers these three values:
from - The sender of the broadcast
title - The message title/name
data - (optional) additional data struct
Use remove_receiver with its name to stop receiving messages in its callback.
Broadcast Use the send function on a sender to send out a broadcast message.
It contains three members:
from - the sender of the broadcast
title - the name of the broadcast (this one must pass the message_filter of a receiver)
data - optional struct that holds any additional data for this broadcast.

How to use the subsystem: If you want to send something, just call
BROADCASTER.send(your_sender|self, "your_message", [your_data_struct]).

Here is a small example:

var snd = new Sender();
snd.add_receiver(self, "achievement_counter", "*_died", my_achievement_counter_function);

... when a monster dies you could invoke

snd.send(self, "dragon_died");

Naming your messages and receivers

It is very important to know, that the names of your receivers must be system-wide unique!
If you add a receiver with an already existing name, it will replace the former one.

Important

Keep in mind: Adding a receiver with the same name as an existing one, will replace the existing. So take care, how you name your receivers, as this can be a useful feature, or a trap, depending on how you use it.
As an example, naming a receiver "active_weapon" might be a good idea, as any weapon that gets activated could just add itself as a receiver under the same name and replacing the so-far active weapon with itself in one go.
On the other hand, naming a receiver in a monster "active_weapon" is a bad idea, when there are many monsters on the screen, they would permanently replace each other for the broadcast. To have a unique name for each instance, consider using the macro MY_NAME as part of the receiver name, like MY_NAME + "active_weapon", as this resolves to the object name plus the instance id and it always delivers a unique string for one object instance.

raptor also uses the broadcasting system internally, all its messages are prefixed with __raptor_<message_name> to avoid collisions with your own custom messages.
However, it might be handy to listen to some of the raptor-internal messages, as some of them can be of interest for your running game.
You can find the full list of internal messages at Raptor-internal broadcasts.

The message_filter

In larger games, there are many messages sent through the senders and a receiver normally does not need to catch all of them. As an example, the achievement receiver in the code shown above shall only count, when a monster dies, so it receives only messages that end with _died.

The title of a message is a string defined by you. So you should set up a naming system for your messages to make them filterable.

Supported filter types

The message_filter uses the string_match function from the string utilities script, which is also part of raptor. This function supports four types of wildcards:

Wildcard Syntax Description
*anything * at the beginning Matches all string that end with "anything"
anything* * at the end Matches all string that start with "anything"
*anything* * at the beginning and the end Matches all string that contain "anything"
anything No * at all Exact match

The constructors

Sender

var snd = new Sender();

The Sender has no constructor parameters. You can create as many as you like.

Important

Keep in mind, one sender is created for you by raptor. You can reach it through the BROADCASTER macro. In most games, this one global broadcaster will be sufficient.

Receiver


Tip

If your callback function returns true, this receiver will be removed after processing the message. This is a comfortable shortcut to remove a receiver, after its work is done. As an example, if the achievement "Kill 100 Monsters" is reached, this receiver no longer must count dying monsters, so it can be removed. Instead of keeping the receiver in an instance variable and then referencing it from within the callback, simply return true, when the work is done. If the callback function doesn't return anything, the receiver stays in the queue (which is the default).

BROADCASTER.add_receiver(self, "kill_monsters_achievement_counter", "*_died",
    function(broadcast) {
        // Here you can access all data in the broadcast like this:
        // broadcast.from  --> contains the sender of the message
        // broadcast.title --> the title of the message (like "dragon_died")
        // broadcast.data  --> an optional data struct containing additional info or <undefined>
    }

The add_receiver method returns self for call chaining, so you can add multiple receivers in one go, like you do with the StateMachine.


Broadcast

The Broadcast is the object sent to your callback method, when you Send a broadcast. It contains these members:

Member Datatype Contains
uniqueid integer Every broadcast has a uniqueid. It's a numeric value, unique for each send call, counting up
handled bool Initialized with false. Set it to true, to mark this broadcast as being done.
The send loop will abort then and stop sending this broadcast to the remaining recipients
from object instance The sender of this broadcast
title string The string you set as title argument to the send method
data struct Any custom data struct you supplied to the send method

When you send this broadcast...:

BROADCASTER.send(self, "monster_died", { monster_id: 42 }));

...this will be received by all registered receivers, whose filter matches:

{
    sender = (whoever has been `self` in the send-call above)
    title = "monster_died" (as string)
    handled = false
    uniqueid = integer number
    data = {
        monster_id: 42
    }
}
⚠️ **GitHub.com Fallback** ⚠️