User:Antony Fairport/Scripts/Simple Security System

From Second Life Wiki
Jump to navigation Jump to search

Originally documented here.

TODO: Document here rather that push people over to the blog.

<lsl> ////////////////////////////////////////////////////////////////////// // 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;
       }
   }

} </lsl>