---
layout: doc
title: general / message_doc
---
# message_doc

## the message() efun

`message()` is the FluffOS efun designed to make communication efuns more
generic. It attaches a classification (the message `type`) to every message so
that recipients can decide how to handle it, which in turn makes it
straightforward to communicate intelligently with capable clients.

Here is the manual page for `message()`:

```c
void message(mixed type, mixed message,
             string | string * | object | object * target,
             void | object | object * exclude);
```

`message()` calls `receive_message(mixed type, mixed message)` in all message
recipients (derived from the target list) excluding those in the exclude list.
This basically tells the objects the message through the `receive_message` apply.
The `exclude` argument is optional.

`type` is an arbitrary classification for the message. The driver does not
interpret it or forward it to the client on its own; it is simply passed along
to `receive_message` in each recipient, where your LPC code decides what to do
with it — for example, filtering out certain types, or forwarding it to a client
as part of some structured communication protocol. An example would be 'combat',
'shout', 'emergency', 'system', 'room description', etc.

`message` is the message to be sent, normally a string.

`target` is a list of objects to be sent the message. This can be either a
single object string or object pointer, or may be an array of either.
If a target is non-living, all objects in its environment will receive
the message.

`exclude` is a list of objects that should not receive the message. This
can be a single object pointer or an array of object pointers.

The most important element of this function is the `type`. Because every message
sent through `message()` carries one, the recipient's `receive_message` can
decide what to do per message — display it, discard it, filter by category, or
hand it to a client.

Note that this classification applies only to content sent via `message()`. The
traditional output efuns — `say()`, `tell_object()`, `shout()`, `write()`,
`tell_room()` — deliver their text through the `catch_tell` apply instead and
never reach `receive_message`. A mudlib that wants all of its output to be
classifiable typically routes that output through `message()` (often behind
simul_efuns), choosing whatever type names suit it, such as "shout", "say",
"tell", or "emote".

An example would be overriding the `shout()` efun in your `simul_efun` object
to use `message()`:

```c
void shout(string msg) {
    object *exclude = ({});

    if(this_player())
        exclude += ({ this_player() });

    message("shout", msg, users(), exclude);
}
```

Note the exclusion of `this_player()`. The built-in `shout()` and `say()` efuns
never echo back to the object performing the action (the command giver), so an
override that reproduces their behavior must keep that semantic and exclude
`this_player()` from the recipients.

Given this, let's say that you wanted to implement a quick and easy
earmuff ability (the ability to mask shouts). In your user (player)
object, you would have the function `receive_message`. Here's the
simplest implementation possible:

```c
void receive_message(string type, string msg) {
    receive(msg);
}
```

This simply takes all messages generated by the `message()` efun and
displays them to the user. However, you could imagine a simple
earmuffs implementation on top of this:

```c
string *muffled = ({});

void muffle_type (string type)
{
    muffled += ({ type });
}

void receive_message (string type, string msg)
{
    if (member_array(type, muffled) == -1) {
        receive(msg);
    }
}
```

Now you can see that if a particular type is muffled (say, "shout"
for example), the text never gets displayed, but for other types it
does.

A single coarse type is rarely enough. Suppose a player muffles the "shout"
type, but an admin needs to announce that the system is going down in five
minutes. If that announcement is also sent (via `message()`) as type "shout",
the player misses it. This is why a mudlib usually defines a broader set of
types — for example a dedicated "broadcast" type for important announcements
that everyone should see, perhaps one that muffling is not permitted to block.

You can layer convenience simul_efuns on top of `message()` so that
writing content is as easy as the traditional `write()`/`say()` efuns
while still classifying every message. For example, an `emote()`
simul_efun that all soul commands use, passing the "emote" type, might
look like:

```c
varargs int emote(object emoter, string self_message,
                  string other_message, mixed emotee,
                  string target_message, string modifier);

// emoter         - the object doing the emoting
// self_message   - the message displayed to the emoter
// other_message  - the message displayed to the whole room
// emotee         - the target of the emote (i.e. kick huthar)
// target_message - the message displayed to the emotee
// modifier       - any extra modifier to tack on to the end of the
//                  emote string (i.e. adverbs: smiles happily,
//                  cheerfully, etc.) — only really complex soul
//                  commands need this
```

## Talking to clients

Selective muffling is just one simple thing the `type` classification makes
possible. The larger payoff comes when the type is used to drive an out-of-band
client protocol: rather than only displaying the text, `receive_message` can
forward structured data to a capable client so it can route room descriptions,
conversation, combat, and status into separate windows or a status line.

When this document was originally written, no such standard existed, and it went
on to propose an ad-hoc `"type:length:msg"` text convention for a hypothetical
"smart client". That role is now filled by standardized out-of-band protocols
that FluffOS supports natively; use these rather than inventing your own wire
format:

- [GMCP](../../apply/interactive/gmcp.md) — Generic MUD Communication Protocol
- [MSDP](../../apply/interactive/msdp.md) — Mud Server Data Protocol
- [MXP](../../apply/interactive/mxp_tag.md) — MUD eXtension Protocol
- [MSP](../../apply/interactive/msp_enable.md) — MUD Sound Protocol
- [ZMP](../../apply/interactive/zmp.md) — Zenith MUD Protocol

A typical pattern is to keep using `message()` with a meaningful `type` for
in-game classification, and have `receive_message` (or the relevant protocol
apply) hand a structured payload to the client through the appropriate efun,
such as [`send_gmcp()`](../../efun/interactive/send_gmcp.md).
