The sender would have code like this
integer commChannel = -837465;
...
llRegionSay( commChannel, "start");
...
integer commChannel = -837465;
default {
state_entry() {
llListen( commChannel, "", NULL_KEY, "");
}
listen( integer channel, string fromName,
key fromKey, string msg ){
key fromKey, string msg ){
if ( channel == commChannel ) {
if ( msg == "start" ) {
llSay(PUBLIC_CHANNEL, "'"+fromName+"' says start");
} else if ( msg == "stop" ) {
llSay(PUBLIC_CHANNEL, "'"+fromName+"' says stop");
}
}
}
}
____________________Communication often consists pairs of messages that comprise a transaction. For a ping-pong transaction which allows one object to find many other objects, the receiver would have code like this
listen( integer channel, string fromName, key fromKey,
string msg ){
string msg ){
if ( channel == commChannel ) {
integer match = llListFindList(
[ "start", "stop", "ping" ], [msg] );
[ "start", "stop", "ping" ], [msg] );
if ( match == 0 ) {
....
} else if ( match == 1 ) {
....
} else if ( match == 2 ) {
llRegionSayTo( fromKey, commChannel, "pong" );
llRegionSayTo( fromKey, commChannel, "pong" );
}
}
}
The receiver knows that the pong should go back to the emitter of the ping. Therefore the pong emitter may use llRegionSayTo() to send the message to a specific object.
The pinger code would include a listen handle that receives the pong message. To make a list of responder keys it could have code like this:
list pongerKeyList = [];
listen( integer channel, string fromName,
key fromKey, string msg ){
key fromKey, string msg ){
if ( channel == commChannel ) {
integer match = llListFindList( [ "pong" ], [msg] );
if ( match == 0 ) {
pongerKeyList += fromKey;
}
}
}
____________________The receiver of a message can extract substantial information from the key of the sender using llGetObjectDetails().
listen( integer channel, string fromName,
key fromKey, string msg ){
key fromKey, string msg ){
if ( channel == commChannel ) {
if ( msg == "pong" ) {
list a = llGetObjectDetails( fromKey,
[ OBJECT_NAME, OBJECT_OWNER,
OBJECT_POS, OBJECT_ROT ] );
[ OBJECT_NAME, OBJECT_OWNER,
OBJECT_POS, OBJECT_ROT ] );
llSay(PUBLIC_CHANNEL, "pong response: "+llList2CSV(a));
}
}
}
____________________Messages carry additional information by concatenating values using a special character pattern which does not appear within any values. The message sender uses llDumpList2String() to build the message. The receiver used llParseStringKeepNulls() to separate the message into a list of string fields. These string fields are converted back into values using casts. The ping sender would have code like this:
touch_start( integer nTouch ) {
float jitterPongMax = 4;
llRegionSay( commChannel, llDumpList2String(
[ "ping", jitterPongMax , llGetUnixTime(),
llRegionSay( commChannel, llDumpList2String(
[ "ping", jitterPongMax , llGetUnixTime(),
llGetPos() ], "|"));
}
}
The ping receiver/pong sender would have code like this:
listen( integer channel, string fromName,
key fromKey, string msg ){
if ( channel == commChannel ) {
list a = llParseStringKeepNulls( msg, ["|"], [] );
string verb = llList2String(a,0);
integer match = llListFindList(
[ "start", "stop", "ping" ], [verb] );
if ( match == 0 ) {
...
string verb = llList2String(a,0);
integer match = llListFindList(
[ "start", "stop", "ping" ], [verb] );
if ( match == 0 ) {
...
} else if ( match == 1 ) { ...
} else if ( match == 2 ) {
float jitterMax = (integer)llList2String(a,0);
integer sendTime = (integer)llList2String(a,1);
vector pingerPos = (vector) llList2String(a,3);
llSleep( llFrand(jitterMax ) );
llRegionSayTo( fromKey, commChannel, "pong" );
.... }
} else if ( match == 2 ) {
float jitterMax = (integer)llList2String(a,0);
integer sendTime = (integer)llList2String(a,1);
vector pingerPos = (vector) llList2String(a,3);
llSleep( llFrand(jitterMax ) );
llRegionSayTo( fromKey, commChannel, "pong" );
.... }
}
}
____________________
Notes:
[end]
Notes:
- If your system will be deployed across region boundaries, then use llShout(), which has a range of 100 meters.
- If the messages pass between one agent's attachments, use llWhisper(), which has a range of 10 meters.
- In the last example llSleep(llFrand(jitterMax)) prevents all the pongers from responding at the same time. There are limits to how many messages can be queued by a region.
- llParseStringKeepNulls() is used because string values may be zero length strings.
- llListFindList() and subsequent integer comparisons is more efficient that a series of string comparisons.