Difference between revisions of "LlListen"

From Second Life Wiki
Jump to navigation Jump to search
(Undo revision 1186384. I'm sorry, but a note explaining that scripts behave normally, isn't needed.)
m (added intra-wiki links and comment)
Line 26: Line 26:
|also_tests
|also_tests
|also_articles
|also_articles
|notes=*Avoid channel 0 and set name or id where possible to avoid [http://rpgstats.com/wiki/index.php?title=Lag Lag]. llListen(0,"","","") can be extremely laggy as it listens to all chat from everyone in chat range and so it should be avoided at all cost.
|notes=*Avoid channel [[PUBLIC_CHANNEL]] and set {{LSLP|name}} or {{LSLP|id}} where possible to avoid [http://rpgstats.com/wiki/index.php?title=Lag Lag]. <code>[[llListen]]([[PUBLIC_CHANNEL]], "", [[NULL_KEY]],"")</code> can be extremely laggy as it listens to all chat from everyone in chat range and so it should be avoided at all cost.


*In November 2007, Kelly Linden offered [https://lists.secondlife.com/pipermail/secondlifescripters/2007-November/001993.html this explanation] to help scripters plan listeners more efficiently:
*In November 2007, [[User:Kelly_Linden|Kelly Linden]] offered [https://lists.secondlife.com/pipermail/secondlifescripters/2007-November/001993.html this explanation] to help scripters plan listeners more efficiently:
:#Chat that is said gets added to a history.
:#Chat that is said gets added to a history.
:#A script that is running and has a listen event will ask the history for a chat message during its slice of run time.
:#A script that is running and has a [[listen]] [[event]] will ask the history for a chat message during its slice of run time.
:# When the script asks the history for a chat message the checks are done in this order:
:# When the script asks the history for a chat message the checks are done in this order:
:#* channel
:#* {{LSLP|channel}}
:#* self chat (prims can't hear themselves)
:#* self chat (prims can't hear themselves)
:#* distance/[[llRegionSay|RegionSay]]
:#* distance/[[llRegionSay|RegionSay]]
:#* key
:#* {{LSLP|id}}
:#* name
:#* {{LSLP|name}}
:#* message
:#* {{LSLP|msg}}
:# If a message is found then a listen event is added to the event queue.
:# If a {{LSLP|msg}} is found then a [[listen]] [[event]] is added to the [[event]] queue.
:
:
:The key/name/message checks only happen at all if those are specified of course.
:The {{LSLP|id}}/{{LSLP|name}}/{{LSLP|msg}} checks only happen at all if those are specified of course.
:
:
:So, the most efficient communication method is [[llRegionSay]] on a rarely used channel.
:So, the most efficient communication method is [[llRegionSay]] on a rarely used {{LSLP|channel}}.
:Nowadays, [[llRegionSayTo]] is to be preferred, where appropriate.
:Nowadays, [[llRegionSayTo]] is to be preferred, where appropriate.
*The integer returned can be assigned to a variable (then called a handle) and used to control the listen via [[llListenRemove]] or [[llListenControl]]. These handles are assigned sequentially starting at 1. If an llListen is repeated with the exact same filters as a currently active listener, then the same handle number is returned. If an llListen's filters do not match any currently active listener, then the next handle in sequence is allocated (it will not re-allocate a recently removed handle).
*The integer returned can be assigned to a variable (then called a handle) and used to control the listen via [[llListenRemove]] or [[llListenControl]]. These handles are assigned sequentially starting at 1. If an [[llListen]] is repeated with the exact same filters as a currently active listener, then the same handle number is returned. If an [[llListen|llListen's]] filters do not match any currently active listener, then the next handle in sequence is allocated (it will not re-allocate a recently removed handle).
*If you are using multiple listens in one script, each listen can be assigned its own handle with which to control it.
*If you are using multiple listens in one script, each listen can be assigned its own handle with which to control it.
|caveats=*On [[state]] change or [[llResetScript|script reset]] all listens are removed automatically.
|caveats=*On [[state]] change or [[llResetScript|script reset]] all listens are removed automatically.
**A state change can be used as a shortcut to releasing listens.
**A [[state]] change can be used as a shortcut to releasing listens.
*Only 65 listens can simultaneously be open in any single script.
*Only 65 listens can simultaneously be open in any single script.
**If this number is exceeded ''Script run-time error'' and ''Too Many Listens'' errors occur.
**If this number is exceeded ''Script run-time error'' and ''Too Many Listens'' errors occur.
*The standard SL viewer can only send chat on negative channels through [[llDialog]] or [[llTextBox]] responses. (Several third party viewers can use these channels from the chat bar.) For maximum compatibility, negative channels are best suited for applications that do not require direct avatar chat.
*The standard SL viewer can only send chat on negative channels through [[llDialog]] or [[llTextBox]] responses. (Several third party viewers can use these channels from the chat bar.) For maximum compatibility, negative channels are best suited for applications that do not require direct avatar chat.
*Once a listen is registered its filters cannot be updated, if the listen is registered to [[llGetOwner]], the listen will remain registered to the old owner upon owner change.
*Once a [[listen]] is registered its filters cannot be updated, if the listen is registered to [[llGetOwner]], the listen will remain registered to the old owner upon owner change.
**[[CHANGED_OWNER|Owner change]] can be detected with the [[changed]] event.
**[[CHANGED_OWNER|Owner change]] can be detected with the [[changed]] event.
**To work around this the old listen will need to be closed and a new one opened for the new owner.
**To work around this the old listen will need to be closed and a new one opened for the new owner.
Line 57: Line 57:
**Chat indirectly generated (as a result of [[llDialog]], [[llTextBox]] or from a linked prim) can be heard if in range.
**Chat indirectly generated (as a result of [[llDialog]], [[llTextBox]] or from a linked prim) can be heard if in range.
|examples=
|examples=
Trivial example to listen to any chat from the object owner and respond once. To reduce lag and avoid spamming surrounding users, it is vastly preferable to listen on channels other than 0 and to trigger the listen event by chatting on an alternative channel such as '/5 hello'.
Trivial example to [[listen]] to any chat from the [[object]] owner and respond once. To reduce lag and avoid spamming surrounding users, it is vastly preferable to listen on {{LSLP|channel}}s other than [[PUBLIC_CHANNEL]] and to trigger the listen event by chatting on an alternative channel such as <code>/5 hello</code>.
<lsl>
{{{!}} class="sortable" width="100%" {{Prettytable}}
// says beep to owner the first time owner says something in main chat;
{{!}}- {{Hl2}}
! '''Single listen handle'''
{{!}}-
{{!!}}<lsl>
// Says beep to owner the first time owner says something in main chat
//  and then stops listening
 
integer listenHandle;
integer listenHandle;
remove_listen_handle()
{
    llListenRemove(listenHandle);
//  because active listen handles are assigned a positive integer number
//  we set the handle's value to zero so we know it has been removed
    listenHandle = FALSE;
}


default
default
Line 66: Line 82:
     state_entry()
     state_entry()
     {
     {
        // Registers the listen to the current owner of the object at the moment of the call
//     Change channel to a positive integer number
        // Change PUBLIC_CHANNEL (0) to another positive number to listen for '/5 hello' style of chat.
//     to listen for '/5 hello' style of chat.
 
//      target only the owner's chat on channel PUBLIC_CHANNEL (0)
         listenHandle = llListen(PUBLIC_CHANNEL, "", llGetOwner(), "");
         listenHandle = llListen(PUBLIC_CHANNEL, "", llGetOwner(), "");
     }
     }
Line 73: Line 91:
     listen(integer channel, string name, key id, string message)
     listen(integer channel, string name, key id, string message)
     {
     {
        //we filtered to only listen to the current owner in the llListen call above!
//     we filtered to only listen on PUBLIC_CHANNEL (0)
//      to the owner's chat in the llListen call above
 
         llOwnerSay("beep");
         llOwnerSay("beep");
        llListenRemove(listenHandle);// Stop listening until script is reset
 
//     stop listening until script is reset
        remove_listen_handle();
     }
     }


     on_rez(integer start_param)// triggered when rezzed from agent's or prim's inventory
     on_rez(integer start_param)
     {
     {
         llResetScript();// by resetting on rez, the script registers a new listen handle
         llResetScript();
     }
     }


    // Registering a new listen handle with the new owner by script reset
     changed(integer change)
     changed(integer change)// triggered by various events that change the task
     {
     {
         if (change & CHANGED_OWNER)// when a new owner is detected
         if (change & CHANGED_OWNER)
         {
         {
             llResetScript();
             llResetScript();
Line 93: Line 114:
}
}
</lsl>
</lsl>
{{!}}}
|cat1=Communications
|cat1=Communications
|cat2=Chat
|cat2=Chat

Revision as of 02:08, 5 January 2014

Summary

Function: integer llListen( integer channel, string name, key id, string msg );
0.0 Forced Delay
10.0 Energy

Sets a callback for msg on channel from name and id.
Returns a handle (an integer) that can be used to deactivate or remove the listen.

• integer channel input chat channel, any integer value (-2147483648 through 2147483647)
• string name filter for specific prim name or avatar legacy name
• key id filter for specific group, avatar or prim UUID
• string msg filter for specific message

If msg, name or id are blank they are not used to filter incoming messages. If id is an invalid key or a null key, it is considered blank.

Specification

For the listen event to be triggered it must first match the criteria set forth by the filters; only when all the criteria have been met is a listen event generated. First the message must have been transmitted on channel. If id is both a valid key and not a null key then the speaker's key must be equivalent[2] to id. If name is set then the speaker's legacy name must match name exactly (case sensitive). If msg is set then the spoken message must match msg exactly (case sensitive).

Channel Constant Description
DEBUG_CHANNEL 0x7FFFFFFF Chat channel reserved for script debugging and error messages, broadcasts to all nearby users.
PUBLIC_CHANNEL 0x0 Chat channel that broadcasts to all nearby users. This channel is sometimes referred to as: open chat, local chat and public chat.

Caveats

  • Messages sent on channel zero[1] and DEBUG_CHANNEL are throttled to a rate of <200/10sec, per region, per owner/user.
    • Once the rate is exceeded, all following messages on channel zero or DEBUG_CHANNEL will be dropped until the send rate is again below 200/10sec for the previous 10 sec. Dropped messages, despite being dropped still count against the limit.
  • On state change or script reset all listens are removed automatically.
    • A state change can be used as a shortcut to releasing listens.
  • Only 65 listens can simultaneously be open in any single script.
    • If this number is exceeded Script run-time error and Too Many Listens errors occur.
  • The standard SL viewer can only send chat on negative channels through llDialog or llTextBox responses. (Several third party viewers can use these channels from the chat bar.) For maximum compatibility, negative channels are best suited for applications that do not require direct avatar chat.
  • Once a listen is registered its filters cannot be updated, if the listen is registered to llGetOwner, the listen will remain registered to the old owner upon owner change.
    • Owner change can be detected with the changed event.
    • To work around this the old listen will need to be closed and a new one opened for the new owner.
  • A prim cannot hear/listen to chat it generates. It can, however, hear a linked prim.
    • Chat indirectly generated (as a result of llDialog, llTextBox or from a linked prim) can be heard if in range.

Examples

Trivial example to listen to any chat from the object owner and respond once. To reduce lag and avoid spamming surrounding users, it is vastly preferable to listen on channels other than PUBLIC_CHANNEL and to trigger the listen event by chatting on an alternative channel such as /5 hello.

Single listen handle
<lsl>

// Says beep to owner the first time owner says something in main chat // and then stops listening

integer listenHandle;

remove_listen_handle() {

   llListenRemove(listenHandle);

// because active listen handles are assigned a positive integer number // we set the handle's value to zero so we know it has been removed

   listenHandle = FALSE;

}

default {

   state_entry()
   {

// Change channel to a positive integer number // to listen for '/5 hello' style of chat.

// target only the owner's chat on channel PUBLIC_CHANNEL (0)

       listenHandle = llListen(PUBLIC_CHANNEL, "", llGetOwner(), "");
   }
   listen(integer channel, string name, key id, string message)
   {

// we filtered to only listen on PUBLIC_CHANNEL (0) // to the owner's chat in the llListen call above

       llOwnerSay("beep");

// stop listening until script is reset

       remove_listen_handle();
   }
   on_rez(integer start_param)
   {
       llResetScript();
   }
   changed(integer change)
   {
       if (change & CHANGED_OWNER)
       {
           llResetScript();
       }
   }

} </lsl>

Notes

  • Avoid channel PUBLIC_CHANNEL and set name or id where possible to avoid Lag. llListen(PUBLIC_CHANNEL, "", NULL_KEY,"") can be extremely laggy as it listens to all chat from everyone in chat range and so it should be avoided at all cost.
  1. Chat that is said gets added to a history.
  2. A script that is running and has a listen event will ask the history for a chat message during its slice of run time.
  3. When the script asks the history for a chat message the checks are done in this order:
    • channel
    • self chat (prims can't hear themselves)
    • distance/RegionSay
    • id
    • name
    • msg
  4. If a msg is found then a listen event is added to the event queue.
The id/name/msg checks only happen at all if those are specified of course.
So, the most efficient communication method is llRegionSay on a rarely used channel.
Nowadays, llRegionSayTo is to be preferred, where appropriate.
  • The integer returned can be assigned to a variable (then called a handle) and used to control the listen via llListenRemove or llListenControl. These handles are assigned sequentially starting at 1. If an llListen is repeated with the exact same filters as a currently active listener, then the same handle number is returned. If an llListen's filters do not match any currently active listener, then the next handle in sequence is allocated (it will not re-allocate a recently removed handle).
  • If you are using multiple listens in one script, each listen can be assigned its own handle with which to control it.

See Also

Events

•  listen

Functions

•  llListenRemove Removes a listen
•  llListenControl Enables/Disables a listen
•  llWhisper Sends chat limited to 10 meters
•  llSay Sends chat limited to 20 meters
•  llShout Sends chat limited to 100 meters
•  llRegionSay Sends chat limited current sim
•  llRegionSayTo Sends chat region wide to a specific avatar, or their attachments, or to a rezzed object of known UUID

Deep Notes

Footnotes

  1. ^ Channel zero is also known as: PUBLIC_CHANNEL, open chat, local chat and public chat
  2. ^ In general terms this means the matching for id is not case sensitive. See key#equivalency for details on key equivalency.

Signature

function integer llListen( integer channel, string name, key id, string msg );