////////////////////////////////////////////////////////////////////// // Simple security system. // By Antony Fairport. // // Revision history. // ================= // // 2011-06-27 // Initial version. ////////////////////////////////////////////////////////////////////// // Constants. string CONFIG_FILE = "Security"; ////////////////////////////////////////////////////////////////////// // Global configuration. float g_nRange; // Range to scan. float g_nFrequency; // Frequency of checks. list g_lOwners; // Owner list. list g_lAccess; // Access list. ////////////////////////////////////////////////////////////////////// // Config reading globals. key g_keyConfig; integer g_iConfig; ////////////////////////////////////////////////////////////////////// // Is the given avatar on the given list? integer AvatarInList( string sAvatar, list l ) { return ~llListFindList( l, [ sAvatar ] ); } ////////////////////////////////////////////////////////////////////// // Is the given avatar an owner? integer IsOwner( string sName ) { return AvatarInList( sName, g_lOwners ); } ////////////////////////////////////////////////////////////////////// // Does the given avatar have access? integer HasAccess( string sName ) { return AvatarInList( sName, g_lAccess ); } ////////////////////////////////////////////////////////////////////// // Eject the intruder. Eject( key keyIntruder ) { // Tell the intruder what we're doing to them. llInstantMessage( keyIntruder, "You do not have access to this location. Sending you home." ); // And send them home. llTeleportAgentHome( keyIntruder ); } ////////////////////////////////////////////////////////////////////// // Default state. default { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Read the configuration. state Configure; } } ////////////////////////////////////////////////////////////////////// // Configuration state. state Configure { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Let the user know what's happening. llWhisper( 0, "Reading configuration." ); // Clear out the config. g_nRange = 96.0; g_nFrequency = 5.0; g_lOwners = []; g_lAccess = []; // If it looks like we've got config... if ( llGetInventoryType( CONFIG_FILE ) == INVENTORY_NOTECARD ) { // ...start reading it. g_keyConfig = llGetNotecardLine( CONFIG_FILE, g_iConfig = 0 ); } else { // Tell the user things aren't good. llWhisper( 0, "No security configuration found. Turning off." ); } } ////////////////////////////////////////////////////////////////// // Handle data server responses. dataserver( key queryid, string data ) { // If this is our query... if ( queryid == g_keyConfig ) { // If this isn't the end of the file... if ( data != EOF ) { // If the line doesn't look like it's a comment, and it isn't empty... if ( ( llGetSubString( data, 0, 0 ) != "#" ) && ( llStringTrim( data, STRING_TRIM ) != "" ) ) { // Split the line into a list. list sLineData = llParseString2List( data, [ "=" ], [] ); // Pull out the setting name. string sSetting = llToLower( llStringTrim( llList2String( sLineData, 0 ), STRING_TRIM ) ); // Pull out the setting value. string sValue = llStringTrim( llList2String( sLineData, 1 ), STRING_TRIM ); // Owner? if ( sSetting == "owner" ) { g_lOwners += [ sValue ]; g_lAccess += [ sValue ]; llWhisper( 0, "Owner: " + sValue ); } // Access list? else if ( sSetting == "access" ) { g_lAccess += [ sValue ]; llWhisper( 0, "Access: " + sValue ); } // Range? else if ( sSetting == "range" ) { g_nRange = (float) sValue; llWhisper( 0, "Range: " + sValue ); } // Frequency? else if ( sSetting == "frequency" ) { g_nFrequency = (float) sValue; llWhisper( 0, "Frequency: " + sValue ); } } // Read the next line. g_keyConfig = llGetNotecardLine( CONFIG_FILE, ++g_iConfig ); } else { // Config read. Get protecting. state Protect; } } } } ////////////////////////////////////////////////////////////////////// // Paused state -- does nother but waits to be activated again. state Paused { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Tell the user we're paused. llWhisper( 0, "Security protection is paused." ); // And add some hover text too. llSetText( "Security system paused.", < 1.0, 0.0, 0.0 >, 1.0 ); } ////////////////////////////////////////////////////////////////// // Handle a touch. touch_end( integer num_detected ) { // If it's an owner who touched us... if ( IsOwner( llDetectedName( 0 ) ) ) { // Jump back to the protect state. state Protect; } } ////////////////////////////////////////////////////////////////// // Detect change. changed( integer change ) { // If the inventory has changed... if ( change & CHANGED_INVENTORY ) { // ...start over. state Configure; } } } ////////////////////////////////////////////////////////////////////// // Protect state -- does the scanning and ejecting. state Protect { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Let the user know what's happening. llWhisper( 0, "Security protection is enabled." ); // Remove any hover text. llSetText( "", < 1.0, 1.0, 1.0 >, 0.0 ); // Start the sensor. llSensorRepeat( "", "", AGENT_BY_LEGACY_NAME, g_nRange, PI, g_nFrequency ); } ////////////////////////////////////////////////////////////////// // State exit. state_exit() { // Make sure the sensor is removed. llSensorRemove(); } ////////////////////////////////////////////////////////////////// // Handle the sensor result. sensor( integer num_detected ) { integer i; // For each detected avatar... for ( i = 0; i < num_detected; i++ ) { // If they are over our land... if ( llOverMyLand( llDetectedKey( i ) ) ) { // If they're not on the access list... if ( !HasAccess( llDetectedName( i ) ) ) { // Eject them. Eject( llDetectedKey( i ) ); } } } } ////////////////////////////////////////////////////////////////// // Handle a touch. touch_end( integer num_detected ) { // If it's an owner who touched us... if ( IsOwner( llDetectedName( 0 ) ) ) { // Jump to the paused state. state Paused; } } ////////////////////////////////////////////////////////////////// // Detect change. changed( integer change ) { // If the inventory has changed... if ( change & CHANGED_INVENTORY ) { // ...start over. state Configure; } } }