nebadon2025

Deluxe Visitor List

Jan 31st, 2013
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.83 KB | None | 0 0
  1. // Deluxe Visitor Log - keeps track of visitors to the region, storing the information in a notecard to preserve
  2. // the data between script resets, region restarts and the like. When touched by the owner,
  3. // produces a notecard containing the visitor list sorted by number of visits, alphabetically
  4. // by visitor name, and by date of first visit. (If anyone other than the owner touches it,
  5. // they are simply told the number of visitors the region has had.)
  6. //
  7. // Requires the following OSSL functions: osMakeNotecard(), osGetAgents(), osAvatarName2Key()
  8. // Make sure they are allowed in OpenSim.ini for the UUID of the avatar owning the object which contains the script.
  9. //
  10. // Version 1.0 by Warin Cascabel (4 July 2009)
  11. // Version 1.1 by Warin Cascabel (6 July 2009) - set object description to visitors/visits info
  12.  
  13. //======================================== Variables ========================================
  14.  
  15. // ------------------------------ Configuration variables -----------------------------------
  16.  
  17. float TimerInterval = 60.0; // Number of seconds between polling the region for new avatars
  18. string DataNotecard = "Visitor List Data"; // Name of the notecard in which data is stored
  19.  
  20.  
  21. // ------------------------- Internal variables - do not change -----------------------------
  22.  
  23. list Visitors; // Data stored in the format [ UUID, Name, Visits [...]]
  24. list CurrentlyHere; // UUIDs of avatars detected during the previous scan
  25. key DataRequest; // Used for reading in the settings notecard
  26. integer NotecardLine; // Likewise
  27. //======================================== Functions ========================================
  28.  
  29. // AddName() adds the provided details to the master list, or updates the visit count if the person is
  30. // already present in the list.
  31. //
  32. integer AddName( string UUID, string Name )
  33. {
  34. integer TotalVisits = 1;
  35. integer IndexPos = llListFindList( Visitors, [ UUID ] ); // Search for the UUID in our master list
  36. if (IndexPos == -1) // If not found in the list, add them with 1 visit
  37. {
  38. Visitors += [ UUID, Name, (string) 1 ];
  39. }
  40. else // If they were found in the list, increment their visit count
  41. {
  42. integer CountPos = IndexPos + 2;
  43. TotalVisits = llList2Integer( Visitors, CountPos ) + 1;
  44. Visitors = llListReplaceList( Visitors, [ (string) TotalVisits ], CountPos, CountPos );
  45. }
  46. return 1;
  47. }
  48.  
  49.  
  50. // CheckNames() gets the list of agents present in the region, ignores any who were present during the last scan,
  51. // and adds the remainder to the master list (or increments their visit count if they were already in it)
  52. //
  53. CheckNames()
  54. {
  55. integer NamesAdded = 0;
  56. list l = osGetAgents(); // Get the list of all the agents present in the region (better than sensors!)
  57. list RecentScan; // To hold the name and UUID of everyone found, but who was not present during last scan
  58. list RecentUUIDs; // To hold just the UUIDs of everyone found, but who was not present during last scan
  59. list AllUUIDsFound; // To hold the UUIDs of everyone found, regardless of whether or not they were present last time
  60. integer i = llGetListLength( l ); // general iterator variable
  61. //
  62. // First, build a list containing the data of everyone who wasn't found during the previous scan
  63. //
  64. while (i--)
  65. {
  66. string AvatarName = llList2String( l, i ); // Get the full name
  67. list NameParts = llParseString2List( AvatarName, [ " "], [] ); // break it into first and last names
  68. key UUID = osAvatarName2Key( llList2String( NameParts, 0 ), llList2String( NameParts, 1 )); // Get the UUID
  69. AllUUIDsFound += [ UUID ]; // Add their UUID to the list of all UUIDs found
  70. if (llListFindList( CurrentlyHere, [ UUID ] ) == -1) // if we didn't find the person during the previous scan:
  71. {
  72. RecentUUIDs += [ UUID ]; // Add their UUID to the list of new UUIDs found during this scan
  73. RecentScan += [ UUID, AvatarName ]; // Add all their information to the recent scan list
  74. }
  75. }
  76. CurrentlyHere = AllUUIDsFound; // Replace CurrentlyHere with the list of everyone who's present in the region now.
  77. //
  78. // Add anyone new from the most recent scan to the master list, or increase their visit counts if they've already been here before
  79. //
  80. for (i = llGetListLength( RecentScan ); i > 0; i -= 2)
  81. {
  82. string thisUUID = llList2String( RecentScan, i-2 );
  83. NamesAdded += AddName( thisUUID, llList2String( RecentScan, i-1 ));
  84. }
  85. //
  86. // If we actually did anything, write out a new notecard to save the data.
  87. //
  88. if (NamesAdded)
  89. {
  90. if (llGetInventoryKey( DataNotecard ) != NULL_KEY) llRemoveInventory( DataNotecard );
  91. osMakeNotecard( DataNotecard, Visitors );
  92. llSetObjectDesc( (string) (llGetListLength( Visitors ) / 3) + " visitors / " + (string) CountTotalVisits() + " visits" );
  93. }
  94. }
  95.  
  96.  
  97. // CountTotalVisits() returns the total number of visits recorded by all avatars
  98. //
  99. integer CountTotalVisits()
  100. {
  101. integer RetVal = 0;
  102. integer i = llGetListLength( Visitors ) - 1;
  103. for (i = llGetListLength( Visitors ) - 1; i > 0; i -= 3)
  104. {
  105. RetVal += llList2Integer( Visitors, i );
  106. }
  107. return RetVal;
  108. }
  109.  
  110. // DeliverReportNotecard() builds a notecard containing the visitor list sorted three ways: by frequency of visit (descending),
  111. // alphabetically by visitor name, and by date of first visit. It then delivers the notecard to the
  112. // owner, and deletes it from inventory.
  113. //
  114. DeliverReportNotecard()
  115. {
  116. list OrderedList; // to store the list ordered by date of visit
  117. list NameList; // to store the list ordered by avatar name
  118. list VisitList; // to store the list ordered by visit count
  119. list Notecard; // to store the report notecard
  120. integer j = llGetListLength( Visitors );
  121. integer i;
  122. integer VisitorsLogged = j/3;
  123. integer VisitsLogged = CountTotalVisits();
  124. llOwnerSay( (string) (j/3) + " visitors/" + (string) VisitsLogged + " visits logged. Please wait while the full report is generated." );
  125. for (i = 0; i < j; i += 3)
  126. {
  127. string name = llList2String( Visitors, i+1 );
  128. integer visits = llList2Integer( Visitors, i+2 );
  129. string sss = "s";
  130. if (visits == 1) sss = "";
  131. OrderedList += [ llToLower( name ), name + " (" + (string) visits + " visit" + sss + ")" ];
  132. VisitList += [ visits, (string) visits + " : " + name ];
  133. }
  134. if (VisitorsLogged == 1) // OpenSim screws up llList2ListStrided if there's only one stride in the list.
  135. {
  136. OrderedList = llDeleteSubList( OrderedList, 0, 0 );
  137. NameList = OrderedList;
  138. VisitList = llDeleteSubList( VisitList, 0, 0 );
  139. }
  140. else
  141. {
  142. NameList = llList2ListStrided( llDeleteSubList( llListSort( OrderedList, 2, TRUE), 0, 0 ), 0, -1, 2 ); // sort alphabetically
  143. OrderedList = llList2ListStrided( llDeleteSubList( OrderedList, 0, 0 ), 0, -1, 2 );
  144. VisitList = llListSort( VisitList, 2, FALSE ); // sort by descending visit count
  145. VisitList = llList2ListStrided( llDeleteSubList( VisitList, 0, 0 ), 0, -1, 2 ); // Get only the text to display
  146. }
  147. Notecard = [ "Total visitors: " + (string) VisitorsLogged ];
  148. Notecard += [ "Total visits: " + (string) VisitsLogged ];
  149. Notecard += [ "", "Sorted by number of visits: ", "" ] + VisitList;
  150. Notecard += [ "", "Sorted by name:", "" ] + NameList;
  151. Notecard += [ "", "Sorted by date of first visit:", "" ] + OrderedList;
  152. Notecard += [ "", "Total visitors: " + (string) VisitorsLogged ];
  153. Notecard += [ "Total visits: " + (string) VisitsLogged ];
  154. string NotecardName = llGetRegionName() + " visitor list : " + llGetTimestamp();
  155. osMakeNotecard( NotecardName, Notecard );
  156. llGiveInventory( llGetOwner(), NotecardName );
  157. llRemoveInventory( NotecardName );
  158.  
  159. }
  160.  
  161. // ================================ default state handler ==================================
  162.  
  163. default {
  164.  
  165. state_entry() // Read in the saved visitor list data, if it exists, and switch to the running state.
  166. {
  167. Visitors = []; // clear out the visitors list
  168. if (llGetInventoryKey( DataNotecard ) == NULL_KEY) state running; // switch to running state if the notecard doesn't exist
  169. llOwnerSay( "Reading saved visitor list data" );
  170. NotecardLine = 0;
  171. DataRequest = llGetNotecardLine( DataNotecard, 0 );
  172. }
  173.  
  174. dataserver( key id, string data )
  175. {
  176. if (id != DataRequest) return;
  177. if (data == EOF)
  178. state running;
  179. else
  180. {
  181. data = llStringTrim( data, STRING_TRIM );
  182. if (data != "") Visitors += [ data ];
  183. DataRequest = llGetNotecardLine( DataNotecard, ++NotecardLine );
  184. }
  185. }
  186. }
  187.  
  188. // ================================ running state handler ==================================
  189.  
  190. state running
  191. {
  192. // state_entry(): load in notecard, if present, set a timer, and check region immediately.
  193. //
  194. state_entry()
  195. {
  196. llOwnerSay( "Visitor scanning active" );
  197. llSetTimerEvent( TimerInterval ); // Set the timer for periodic checks
  198. CheckNames(); // Check the region immediately for avatars
  199. }
  200.  
  201. // touch_start() will cause the report card to be generated, if the touch was from our
  202. // owner; otherwise, it will tell the toucher how many visitors the region
  203. // has logged.
  204. //
  205. touch_start( integer foo )
  206. {
  207. if (llDetectedKey( 0 ) == llGetOwner()) // being lazy, and assuming there's only one touch.
  208. DeliverReportNotecard();
  209. else
  210. llInstantMessage( llDetectedKey( 0 ), (string) (llGetListLength( Visitors ) / 3) + " visitor(s) logged, with a total of " + (string) CountTotalVisits() + " visits." );
  211. }
  212.  
  213. // Poll the region every x seconds (as configured by the TimerInterval variable). Rather than using
  214. // sensors, which are limited both in range and in the number of avatars they can detect, we'll use
  215. // the OpenSim-only function osGetAgents().
  216. //
  217. timer()
  218. {
  219. CheckNames();
  220. }
  221.  
  222. // Reset the script if the region has restarted. This mainly restarts the timer and clears out the list
  223. // of people who were detected the last time the region was scanned, but it's good to avoid any other
  224. // unforeseen consequences.
  225. //
  226. changed( integer whatChanged )
  227. {
  228. if (whatChanged & 256) llResetScript();
  229. }
  230. }
Advertisement
Add Comment
Please, Sign In to add comment