Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Deluxe Visitor Log - keeps track of visitors to the region, storing the information in a notecard to preserve
- // the data between script resets, region restarts and the like. When touched by the owner,
- // produces a notecard containing the visitor list sorted by number of visits, alphabetically
- // by visitor name, and by date of first visit. (If anyone other than the owner touches it,
- // they are simply told the number of visitors the region has had.)
- //
- // Requires the following OSSL functions: osMakeNotecard(), osGetAgents(), osAvatarName2Key()
- // Make sure they are allowed in OpenSim.ini for the UUID of the avatar owning the object which contains the script.
- //
- // Version 1.0 by Warin Cascabel (4 July 2009)
- // Version 1.1 by Warin Cascabel (6 July 2009) - set object description to visitors/visits info
- //======================================== Variables ========================================
- // ------------------------------ Configuration variables -----------------------------------
- float TimerInterval = 60.0; // Number of seconds between polling the region for new avatars
- string DataNotecard = "Visitor List Data"; // Name of the notecard in which data is stored
- // ------------------------- Internal variables - do not change -----------------------------
- list Visitors; // Data stored in the format [ UUID, Name, Visits [...]]
- list CurrentlyHere; // UUIDs of avatars detected during the previous scan
- key DataRequest; // Used for reading in the settings notecard
- integer NotecardLine; // Likewise
- //======================================== Functions ========================================
- // AddName() adds the provided details to the master list, or updates the visit count if the person is
- // already present in the list.
- //
- integer AddName( string UUID, string Name )
- {
- integer TotalVisits = 1;
- integer IndexPos = llListFindList( Visitors, [ UUID ] ); // Search for the UUID in our master list
- if (IndexPos == -1) // If not found in the list, add them with 1 visit
- {
- Visitors += [ UUID, Name, (string) 1 ];
- }
- else // If they were found in the list, increment their visit count
- {
- integer CountPos = IndexPos + 2;
- TotalVisits = llList2Integer( Visitors, CountPos ) + 1;
- Visitors = llListReplaceList( Visitors, [ (string) TotalVisits ], CountPos, CountPos );
- }
- return 1;
- }
- // CheckNames() gets the list of agents present in the region, ignores any who were present during the last scan,
- // and adds the remainder to the master list (or increments their visit count if they were already in it)
- //
- CheckNames()
- {
- integer NamesAdded = 0;
- list l = osGetAgents(); // Get the list of all the agents present in the region (better than sensors!)
- list RecentScan; // To hold the name and UUID of everyone found, but who was not present during last scan
- list RecentUUIDs; // To hold just the UUIDs of everyone found, but who was not present during last scan
- list AllUUIDsFound; // To hold the UUIDs of everyone found, regardless of whether or not they were present last time
- integer i = llGetListLength( l ); // general iterator variable
- //
- // First, build a list containing the data of everyone who wasn't found during the previous scan
- //
- while (i--)
- {
- string AvatarName = llList2String( l, i ); // Get the full name
- list NameParts = llParseString2List( AvatarName, [ " "], [] ); // break it into first and last names
- key UUID = osAvatarName2Key( llList2String( NameParts, 0 ), llList2String( NameParts, 1 )); // Get the UUID
- AllUUIDsFound += [ UUID ]; // Add their UUID to the list of all UUIDs found
- if (llListFindList( CurrentlyHere, [ UUID ] ) == -1) // if we didn't find the person during the previous scan:
- {
- RecentUUIDs += [ UUID ]; // Add their UUID to the list of new UUIDs found during this scan
- RecentScan += [ UUID, AvatarName ]; // Add all their information to the recent scan list
- }
- }
- CurrentlyHere = AllUUIDsFound; // Replace CurrentlyHere with the list of everyone who's present in the region now.
- //
- // Add anyone new from the most recent scan to the master list, or increase their visit counts if they've already been here before
- //
- for (i = llGetListLength( RecentScan ); i > 0; i -= 2)
- {
- string thisUUID = llList2String( RecentScan, i-2 );
- NamesAdded += AddName( thisUUID, llList2String( RecentScan, i-1 ));
- }
- //
- // If we actually did anything, write out a new notecard to save the data.
- //
- if (NamesAdded)
- {
- if (llGetInventoryKey( DataNotecard ) != NULL_KEY) llRemoveInventory( DataNotecard );
- osMakeNotecard( DataNotecard, Visitors );
- llSetObjectDesc( (string) (llGetListLength( Visitors ) / 3) + " visitors / " + (string) CountTotalVisits() + " visits" );
- }
- }
- // CountTotalVisits() returns the total number of visits recorded by all avatars
- //
- integer CountTotalVisits()
- {
- integer RetVal = 0;
- integer i = llGetListLength( Visitors ) - 1;
- for (i = llGetListLength( Visitors ) - 1; i > 0; i -= 3)
- {
- RetVal += llList2Integer( Visitors, i );
- }
- return RetVal;
- }
- // DeliverReportNotecard() builds a notecard containing the visitor list sorted three ways: by frequency of visit (descending),
- // alphabetically by visitor name, and by date of first visit. It then delivers the notecard to the
- // owner, and deletes it from inventory.
- //
- DeliverReportNotecard()
- {
- list OrderedList; // to store the list ordered by date of visit
- list NameList; // to store the list ordered by avatar name
- list VisitList; // to store the list ordered by visit count
- list Notecard; // to store the report notecard
- integer j = llGetListLength( Visitors );
- integer i;
- integer VisitorsLogged = j/3;
- integer VisitsLogged = CountTotalVisits();
- llOwnerSay( (string) (j/3) + " visitors/" + (string) VisitsLogged + " visits logged. Please wait while the full report is generated." );
- for (i = 0; i < j; i += 3)
- {
- string name = llList2String( Visitors, i+1 );
- integer visits = llList2Integer( Visitors, i+2 );
- string sss = "s";
- if (visits == 1) sss = "";
- OrderedList += [ llToLower( name ), name + " (" + (string) visits + " visit" + sss + ")" ];
- VisitList += [ visits, (string) visits + " : " + name ];
- }
- if (VisitorsLogged == 1) // OpenSim screws up llList2ListStrided if there's only one stride in the list.
- {
- OrderedList = llDeleteSubList( OrderedList, 0, 0 );
- NameList = OrderedList;
- VisitList = llDeleteSubList( VisitList, 0, 0 );
- }
- else
- {
- NameList = llList2ListStrided( llDeleteSubList( llListSort( OrderedList, 2, TRUE), 0, 0 ), 0, -1, 2 ); // sort alphabetically
- OrderedList = llList2ListStrided( llDeleteSubList( OrderedList, 0, 0 ), 0, -1, 2 );
- VisitList = llListSort( VisitList, 2, FALSE ); // sort by descending visit count
- VisitList = llList2ListStrided( llDeleteSubList( VisitList, 0, 0 ), 0, -1, 2 ); // Get only the text to display
- }
- Notecard = [ "Total visitors: " + (string) VisitorsLogged ];
- Notecard += [ "Total visits: " + (string) VisitsLogged ];
- Notecard += [ "", "Sorted by number of visits: ", "" ] + VisitList;
- Notecard += [ "", "Sorted by name:", "" ] + NameList;
- Notecard += [ "", "Sorted by date of first visit:", "" ] + OrderedList;
- Notecard += [ "", "Total visitors: " + (string) VisitorsLogged ];
- Notecard += [ "Total visits: " + (string) VisitsLogged ];
- string NotecardName = llGetRegionName() + " visitor list : " + llGetTimestamp();
- osMakeNotecard( NotecardName, Notecard );
- llGiveInventory( llGetOwner(), NotecardName );
- llRemoveInventory( NotecardName );
- }
- // ================================ default state handler ==================================
- default {
- state_entry() // Read in the saved visitor list data, if it exists, and switch to the running state.
- {
- Visitors = []; // clear out the visitors list
- if (llGetInventoryKey( DataNotecard ) == NULL_KEY) state running; // switch to running state if the notecard doesn't exist
- llOwnerSay( "Reading saved visitor list data" );
- NotecardLine = 0;
- DataRequest = llGetNotecardLine( DataNotecard, 0 );
- }
- dataserver( key id, string data )
- {
- if (id != DataRequest) return;
- if (data == EOF)
- state running;
- else
- {
- data = llStringTrim( data, STRING_TRIM );
- if (data != "") Visitors += [ data ];
- DataRequest = llGetNotecardLine( DataNotecard, ++NotecardLine );
- }
- }
- }
- // ================================ running state handler ==================================
- state running
- {
- // state_entry(): load in notecard, if present, set a timer, and check region immediately.
- //
- state_entry()
- {
- llOwnerSay( "Visitor scanning active" );
- llSetTimerEvent( TimerInterval ); // Set the timer for periodic checks
- CheckNames(); // Check the region immediately for avatars
- }
- // touch_start() will cause the report card to be generated, if the touch was from our
- // owner; otherwise, it will tell the toucher how many visitors the region
- // has logged.
- //
- touch_start( integer foo )
- {
- if (llDetectedKey( 0 ) == llGetOwner()) // being lazy, and assuming there's only one touch.
- DeliverReportNotecard();
- else
- llInstantMessage( llDetectedKey( 0 ), (string) (llGetListLength( Visitors ) / 3) + " visitor(s) logged, with a total of " + (string) CountTotalVisits() + " visits." );
- }
- // Poll the region every x seconds (as configured by the TimerInterval variable). Rather than using
- // sensors, which are limited both in range and in the number of avatars they can detect, we'll use
- // the OpenSim-only function osGetAgents().
- //
- timer()
- {
- CheckNames();
- }
- // Reset the script if the region has restarted. This mainly restarts the timer and clears out the list
- // of people who were detected the last time the region was scanned, but it's good to avoid any other
- // unforeseen consequences.
- //
- changed( integer whatChanged )
- {
- if (whatChanged & 256) llResetScript();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment