// Advanced chat relay script // Ordinal Malaprop // 2006-03-14 // Inappropriate use of this script, for surveillance etc, // may get you into trouble. I take no responsibility for that. // See Linden Labs' ToS for more details. // We assume that when the owner is within 20m of the relay, they can // already hear the chat and so don't need it relayed. We also assume // that they don't want to hear it when they're offline. // This uses three different states. The advantage of this is that // listens and sensors are not persistent across states, so we don't // have to worry about switching them off. // The default state assumes that the owner is in range (most likely for // the startup state). key gQuery = NULL_KEY; // used for dataserver request default { state_entry() { // Start a sensor to see when the owner is out of range llSensorRepeat("", llGetOwner(), AGENT, 20.0, PI, 2.0); } no_sensor() { // Remove the sensor, just in case the dataserver request is slow // - we don't want it triggering twice. llSensorRemove(); // Do a check to see whether they've gone out of range // because they are offline. This involves making a dataserver // request. gQuery = llRequestAgentData(llGetOwner(), DATA_ONLINE); // NB we don't actually need a "sensor" event as we stay in this // state while the owner is in range } // The dataserver event is activated when we get data about the // online status of the owner dataserver(key queryid, string data) { // If they've gone offline, go to offline state if (queryid == gQuery && !(integer)data) state offline; // otherwise go to out of range state else state out_of_range; } } // If they are out of range, but online... state out_of_range { state_entry() { // Start a timer to detect if owner goes offline, to avoid // spamming their inbox llSetTimerEvent(60.0); // Start a sensor to see when the owner is in range. // Set this with a fairly long interval, to save resources. // It's not that bad if chat is heard twice. llSensorRepeat("", llGetOwner(), AGENT, 20.0, PI, 30.0); // Start up a listen for all chat on channel 0 llListen(0, "", NULL_KEY, ""); } timer() { // Make a dataserver request as above gQuery = llRequestAgentData(llGetOwner(), DATA_ONLINE); } sensor(integer n) { // If the owner comes back within range, change state state default; } listen(integer channel, string name, key id, string message) { // Don't relay the owner's own chat to them - it might be shouted if (id != llGetOwner()) { // Send IM with the appropriate chat in it. // NB if the chat string is VERY long, this may get // truncated. That's unlikely though. llInstantMessage(llGetOwner(), name + ":" + message); } } } // When the owner is offline, don't do anything except check whether // they are still offline. state offline { state_entry() { // Set the timer again llSetTimerEvent(60.0); } timer() { gQuery = llRequestAgentData(llGetOwner(), DATA_ONLINE); } dataserver(key queryid, string data) { if (queryid == gQuery && (integer)data) { // Owner is now online state default; } } }