LSL Wiki Mirror 7-7-7 : llListen

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings ::
integer llListen(integer channel, string name, key id, string msg)

Sets a filter for listening to the specified chat channel. If a message is heard that meets the specified criteria, the object's listen() event handler is invoked.

The name, id, and msg arguments specify the filtering criteria. You can pass the empty string (or NULL_KEY for id) for these to set a completely open filter; this causes the listen() event handler to be invoked for all chat on the channel. To listen only for chat spoken by a specific object or avatar, specify the name and/or id arguments. To listen only for a specific command, specify the (case-sensitive) msg argument. You can also use all the arguments to establish the most restrictive filtering criteria.

This function returns a handle that can be used to deactivate or remove the specific channel filter using llListenControl and llListenRemove. An object should remove any filters it has established when it no longer needs them. Listen filters DO NOT persist and are automatically removed on state changes. The returned handles start at 1, so you can set your handle variable to 0 (zero) when you deactivate a channel and test for that elsewhere when you need to know if it's active or not.

Using many instances of llListen can have a visible effect on sim performance and cause lag. If there is a viable alternative communication method such as llMessageLinked, consider using that instead. Especially avoid listening on channel 0 whenever possible. If you must listen to regular chat conversation, use a filter if possible.

If a script with an llListen "hears" a string longer than the script's amount of available free memory, it will halt with a "stack/heap collision" error before your code in the listen() event handler has a chance to begin executing. As of SL v1.13, a single chat string on any channel can be up to 1023 bytes in length.

Examples

Establishes a completely open filter for avatar chat:
integer handle  = llListen( 0, "", NULL_KEY, "" );

Sets a filter that listens only for chat spoken by the object's owner:
integer handle = llListen( 0, "", llGetOwner(), "" );

Sets a filter that listens on channel 96 for objects named "button":
integer handle = llListen( 96, "button", NULL_KEY, "" );

This could be used, for example, in an elevator that responds to button objects on different floors of a building. Each button object would have the same name, but could identify its floor through the specific message it sends.

To set up to 64 filters on different channels, call llListen repeatedly with different criteria. All messages found by any filter are passed to the same listen event handler. If llListen is called again with the identical criteria, the same listener handle is returned, and the listen() event will only be called once.

If a script goes over its limit of around 64, it crashes with a run-time "Too Many Listens" error.

As of SL 1.5.4, the following does work correctly:
llListen(0, "Froggy", "", "");
llListen(0, "", llGetOwner(), "");

To listen on a single channel, for both chat from the owner and from an object with a certain name, (or any other combination of logic) the best option is to use a single llListen function and an if-else in the listen event.

Selling scripts which contain listeners can be problematic if the id parameter is set to llGetOwner. Be sure to update listen filters or use llResetScript when it changes owners if a script's listeners are set to only listen to their owner.

Example

default
{
    state_entry()
    {
        // listen on channel zero for any chat spoken by the object owner.
        llListen(0,"",llGetOwner(),"");
    }
    
    listen(integer channel, string name, key id, string message)
    {
        // check if the message corresponds to a predefined string.
        // llToLower converts the message to lowercase.
        // This way, "HELLO", "Hello" or "HeLLo" will all work the same way.
        if (llToLower(message) == "hello")
        {
            // if the message from the owner is "hello", respond with "Hello.".
            llSay(0,"Hello.");
        }
    }
}


Potential Issues

Crosstalk

One common problem that is easy to forget about when creating a fancy new scripted widget is crosstalk. This occurs when objects get confused about whose messages are whose. This can be two identical objects which mistake each other's messages or other people's objects which happen to use the same channel and may send problematic (partially compatible and invalid) messages.

There are a number of ways to deal with this problem. A few are listed here:


This is a common issue and the solution can vary widely based on the requirements of a particular problem.


FAQ


Q: I can see how the millions of scripts out there listening to channel 0 would collectively create lots of lag. But, with the callback mechanism and a listener on a private channel, it seems like the only time resources would be used is when an actual message is present. Is this the case?
A: Well, the real server-side problem is the filter. When a script listens on channel 0, it calls the filtering methods every time it hears something. This doesn't create a lot of lag, but tons of these without good use of callback can create some effect on server resources.

Q: Can a wildcard be used for the msg argument? I only want to monitor text that begins with "ls" but can be anything after it ("on", "off", "silence", etc).
A: Wildcards are not supported. You'll want to use llGetSubString or llSubStringIndex in your listen() event.

Q: How close to my listener do I have to be for it to hear me?
A: When saying chat, under 20m. When shouting, 100m. See chat for specifics with dealing with the other chat functions.


Functions | Events | Chat | Communications
There are 14 comments on this page. [Display comments/form]