integer llListen(integer channel, string name, key id, string msg)
Sets a filter for listening to the specified
chat channel while the current state persists. If a message is heard that meets the specified criteria, the object's
listen() event handler is invoked.
Messages are heard from the root prim of a link-set, not the scripted prim, making this command awkward for use in large builds. To avoid this causing a problem, keep root prims towards the center, or most used part, of your builds.
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.
Caution: The
id is the
key of the originator of the chat. In the case of an
agentandavatar it will coorespond with
llGetOwner. In the case of an
object the
key of the root prim (which changes on rez) is returned not the
key of the owner of the prim. To verify that a chat message emitted by an object is owned by a particular
agentandavatar (as is often the case with HUDs) use
llGetOwnerKey and compare that with the value returned by
llGetOwner inside the
listen event.
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:
Sets a filter that listens only for chat spoken by the object's
owner:
Sets a filter that listens on channel 96 for objects named "button":
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 65 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 65, it crashes with a run-time "Too Many Listens"
error.
As of
SL 1.5.4, the following
does work correctly:
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:
- Make filters as tight as possible. For example, use llGetOwner for the id filter.
- For scripts that only need to talk to themselves (dialogs for example) use a random channel. An example can be found on the llFrand page. This strategy can also be utilized when establishing communication with a rezzed object (pass the random integer via llRezObject's integer parameter).
- For private channels across multiple objects use a deterministic equation that results in a unique value yet is repeatable. For example, base the channel on the integers contained in the owner's key. This way two users can both use their copies of the same object in close proximity without difficulty.
- Pass additional data (like a unique command word or the key of the sender or intended recipient) in the message that clues the listener in on the intended recipient or lets the listener know the message isn't from an object they're interested in.
- Avoid channels below 100. If you don't need humans to type the channel and listen on anything below 10 your object will be spammed. Negative channels cannot be used by avatars without an object intermediary, so these are the most ideal for object-object chat.
- Do a llGetOwnerKey(id) == llGetOwner() check in your listen event to filter out chat emitted by objects not owned by the same owner.
This is a common issue and the solution can vary widely based on the requirements of a particular problem.
I know that it is listed that 64 listens per script is the limit but i was able to put in 65. Now 64 may be a suggested limit for memory useage reasons or something but I fit 65 listen functions into 1 script all in 1 state and 1 event and the script had no errors and works fine.
-
BlablablakGumbo
It is not a memory constraint it is a specific run-time error, the wiki is simply wrong the number is 65 not 64, add one more listen to your script and it will fail with two errors
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.
A2: Also, more recently, llRegionSay has been implemented, which allows communication throughout an entire sim. Though it cannot chat on channel 0.'
This article wasn't helpful for you? Maybe the
related article at the LSL Portal is able to bring enlightenment.
Functions |
Events |
Chat |
Communications