Difference between revisions of "Advanced Visitor Counter"
Admindiamond (talk | contribs) |
Admindiamond (talk | contribs) (→Script: - updated with new changes) |
||
Line 64: | Line 64: | ||
key lastCollider;//uuid of the last avi to collide with this object | key lastCollider;//uuid of the last avi to collide with this object | ||
integer lastDay; //day of the month at the last point we checked | integer lastDay; //day of the month at the last point we checked | ||
− | integer lastMonth; //month at the year at the last point we checked | + | integer lastMonth; //month at the year at the last point we checked |
integer lastYear; //year at the last point we checked | integer lastYear; //year at the last point we checked | ||
list daysOfMonthNotecards;//used while processing change of month | list daysOfMonthNotecards;//used while processing change of month | ||
list monthsOfYearNotecards; //used while processing change of year | list monthsOfYearNotecards; //used while processing change of year | ||
integer totalVisitorsCalculation; //used while processing change of month | integer totalVisitorsCalculation; //used while processing change of month | ||
− | list lastPeriodsVisitors; //used while processing change of month | + | list lastPeriodsVisitors; //used while processing change of month |
list admins;//list of people allowed to access the counters menu | list admins;//list of people allowed to access the counters menu | ||
list ignore;//list of people who will not be counted by the visitor counter. | list ignore;//list of people who will not be counted by the visitor counter. | ||
Line 78: | Line 78: | ||
integer menuListen; //used to aid in tracking the listener...shouldn't be needed working aorund OS bugs | integer menuListen; //used to aid in tracking the listener...shouldn't be needed working aorund OS bugs | ||
list notecardsToProcess; //used when processing a new month or year, temp storage of notecard names | list notecardsToProcess; //used when processing a new month or year, temp storage of notecard names | ||
− | integer debug = | + | integer debug = FALSE; |
+ | integer displayComsChannel = -6827416; | ||
integer GetDate (string dayMonthYear) | integer GetDate (string dayMonthYear) | ||
Line 88: | Line 89: | ||
else if (dayMonthYear == "Year") toReturn = llList2Integer(dateComponents, 0); //year | else if (dayMonthYear == "Year") toReturn = llList2Integer(dateComponents, 0); //year | ||
return toReturn; | return toReturn; | ||
− | } //close GetDate | + | } //close GetDate |
CheckDate() | CheckDate() | ||
Line 107: | Line 108: | ||
todaysVisitorsUUIDs = []; //clear the list of visitors uuid's | todaysVisitorsUUIDs = []; //clear the list of visitors uuid's | ||
if (lastMonth != month) ProcessNewMonth(month, year); | if (lastMonth != month) ProcessNewMonth(month, year); | ||
+ | llRegionSay(displayComsChannel, "Reset"); | ||
}//close process new day | }//close process new day | ||
Line 427: | Line 429: | ||
string homeUri = osGetAvatarHomeURI(uuidToCheck);//get the avatars home grid | string homeUri = osGetAvatarHomeURI(uuidToCheck);//get the avatars home grid | ||
string newVisitor = cleanName + "," + homeUri; //this is the line we add to the visitors list | string newVisitor = cleanName + "," + homeUri; //this is the line we add to the visitors list | ||
− | todaysVisitors += newVisitor;//add the line abive to todays visitors list. | + | todaysVisitors += newVisitor;//add the line abive to todays visitors list. |
+ | llMessageLinked(LINK_THIS, 93827334, uuidToCheck, NULL_KEY); //linked message to helpers | ||
+ | llRegionSay(displayComsChannel, uuidToCheck); | ||
if (debug) llOwnerSay("Debug:ProcessDetectedAvatars:" + newVisitor + "added to todays visitors list"); | if (debug) llOwnerSay("Debug:ProcessDetectedAvatars:" + newVisitor + "added to todays visitors list"); | ||
}//close if not on the list already | }//close if not on the list already | ||
Line 473: | Line 477: | ||
collision_start(integer total_number) | collision_start(integer total_number) | ||
{ | { | ||
− | integer detectedType = llDetectedType( | + | integer colliderIndex = 0; |
− | + | for (colliderIndex; colliderIndex < total_number; colliderIndex++) | |
− | + | { | |
− | + | integer detectedType = llDetectedType(colliderIndex); | |
− | + | if (detectedType == 1 || detectedType == 3 || detectedType == 5) | |
− | + | { //only process avatars, no bots or physical objects | |
− | + | key detectedUUID = llDetectedKey(colliderIndex); | |
− | + | if (detectedUUID != lastCollider) | |
− | + | { //if this is the same avi just standing on the dector don't process them | |
− | + | lastCollider = detectedUUID; | |
+ | ProcessDetectedAvatars(); | ||
+ | }//close if not last collider | ||
+ | }//close if detected type is an avatar | ||
+ | } | ||
}//close collision event | }//close collision event | ||
Line 489: | Line 497: | ||
admins = []; | admins = []; | ||
ReadConfigCards("Admin"); | ReadConfigCards("Admin"); | ||
+ | integer detectedIndex = 0; | ||
key toucher = llDetectedKey(0); | key toucher = llDetectedKey(0); | ||
if (~llListFindList(admins, (list)toucher)) | if (~llListFindList(admins, (list)toucher)) | ||
Line 497: | Line 506: | ||
DialogAdminMenu(toucher); | DialogAdminMenu(toucher); | ||
}//close if toucher is on list | }//close if toucher is on list | ||
− | else llRegionSayTo(toucher, PUBLIC_CHANNEL, "Sorry you are not on the admin list and can not use this item."); | + | //else llRegionSayTo(toucher, PUBLIC_CHANNEL, "Sorry you are not on the admin list and can not use this item."); |
}//close touch start event | }//close touch start event | ||
Revision as of 22:19, 16 January 2021
Contents
Introduction
The Covey Advanced Visitor is as complete a visitor tracking system as is reasonably possible to make using just inworld tools. It records the difference between the total number of visits each day and the number of unique visits. Additionally each day a list of the unique visitors is saved. To stop the memory requirements quickly spiralling out of control this information is saved to a notecard at the end of each day. Then at the end of each month, the daily notecards are combined into one for the previous month. Finally, at the end of the year, each of the monthly notecards is combined into one for the entire year.
How it works
This script will turn the prim it is in into a volumetric prim. Volumetric prims act like phantom prims while still allowing the recording of collision events. Each time an avi passes through the prim it checks to see if that avi has already visited the sim today. If they have it will increase the total visits count but not the unique count, nor will it save the avatars details again. If however the avatar has not visited yet today the counter stores the avatars details and increases both the unique and total visitors counter. In addition to the collision based detection, the region is periodically scanned. This scan is done to catch avatars who login into their last location or who bypass the sim landing point.
Instructions
- Make a prim which covers the landing point of your region
- Make a notecard called 'Admin' and use the template below to add in the keys (UUID's) of the avatars you wish to be able to see the contents of the counter.
- Make a notecard called 'Ignore' and use the template below to add in the keys (UUID's) of the avatars you wish the counter to ignore.
- Add the two notecards you just created to the prim
- Create a new script inside the prim you created
- Copy-paste the script below into the one you just created and save.
Admin List
Any avi on the admin list will be able to click the counter to get a folder with all notecards currently held inside the visitor counter.
Ignore List
Any avi on the ignore list will not be counted at all, and will not be recorded. It will be as though they never visited.
Licence
1 BSD 3-Clause License
2 Copyright (c) 2020, Sara Payne
3 All rights reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 1. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
8 2. Redistributions in binary form must reproduce the above copyright notice,
9 this list of conditions and the following disclaimer in the documentation
10 and/or other materials provided with the distribution.
11 3. Neither the name of the copyright holder nor the names of its
12 contributors may be used to endorse or promote products derived from
13 this software without specific prior written permission.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Script
1 list todaysVisitors; //list contains names and grid uri as CSV (uniquire visits in the day)
2 list todaysVisitorsUUIDs;//list contains all unique UUIDS detected today.
3 key lastCollider;//uuid of the last avi to collide with this object
4 integer lastDay; //day of the month at the last point we checked
5 integer lastMonth; //month at the year at the last point we checked
6 integer lastYear; //year at the last point we checked
7 list daysOfMonthNotecards;//used while processing change of month
8 list monthsOfYearNotecards; //used while processing change of year
9 integer totalVisitorsCalculation; //used while processing change of month
10 list lastPeriodsVisitors; //used while processing change of month
11 list admins;//list of people allowed to access the counters menu
12 list ignore;//list of people who will not be counted by the visitor counter.
13 integer menuChannel; //channel the menu listens on
14 integer menuChannelListen; //handle to turn the listener on and off
15 key lastAdmin; //uuid of the last admin to use the menu, used to send time out warning
16 integer timeInterval = 30; //how frequently the sim is checked for visitors
17 integer menuListen; //used to aid in tracking the listener...shouldn't be needed working aorund OS bugs
18 list notecardsToProcess; //used when processing a new month or year, temp storage of notecard names
19 integer debug = FALSE;
20 integer displayComsChannel = -6827416;
21
22 integer GetDate (string dayMonthYear)
23 { //fetches the date, and breaks it down into component parts returning the requested prt
24 list dateComponents = llParseString2List(llGetDate(), ["-"], []);
25 integer toReturn;
26 if (dayMonthYear == "Day") toReturn = llList2Integer(dateComponents, 2);//day of month
27 else if (dayMonthYear == "Month") toReturn = llList2Integer(dateComponents, 1); //month of year
28 else if (dayMonthYear == "Year") toReturn = llList2Integer(dateComponents, 0); //year
29 return toReturn;
30 } //close GetDate
31
32 CheckDate()
33 { //checks to see if the day, month or year has changed form the last check, calling appropirate methods if it has
34 integer year = GetDate("Year");
35 integer month = GetDate("Month");
36 integer day = GetDate("Day");
37 if (day != lastDay) ProcessNewDay(day, month, year);
38 }//close check the date
39
40 ProcessNewDay(integer day, integer month, integer year)
41 { //makes yesterdays visitors note card then resets the lists for today
42 totalVisitorsCalculation = 0; //reset total visitors calc to 0 ready for next time
43 ProcessLastPeriodVisitors("DayOfMonth");
44 GenerateNewNoteCard("DayOfMonth");
45 lastDay = day; //make last day equal today ready for tomorrow
46 todaysVisitors = []; //clear todays visitors list.
47 todaysVisitorsUUIDs = []; //clear the list of visitors uuid's
48 if (lastMonth != month) ProcessNewMonth(month, year);
49 llRegionSay(displayComsChannel, "Reset");
50 }//close process new day
51
52 ProcessNewMonth(integer month, integer year)
53 {
54 totalVisitorsCalculation = 0; //reset total visitors calc to 0 ready for next time
55 PopulateDaysAndMonthsNoteardLists("ProcessNewMonth");//clear lists and generate new ones to work from
56 ProcessLastPeriodVisitors("MonthOfYear");
57 GenerateNewNoteCard("MonthOfYear");
58 lastMonth = month; //make last month this month ready for next month
59 lastPeriodsVisitors = []; //clear to keep memory down while not processing
60 totalVisitorsCalculation = 0; //reset total visitors calc to 0 ready for next time
61 daysOfMonthNotecards = []; //clear list to keep memory use down
62 if (year != lastYear) ProcessNewYear(year);
63 else monthsOfYearNotecards = [];//change of year has not occured so this is not needed, clear to keep memory use down
64 }//close process new month
65
66 ProcessNewYear(integer year)
67 {
68 totalVisitorsCalculation = 0; //reset total visitors calc to 0 ready for next time
69 PopulateDaysAndMonthsNoteardLists("ProcessNewYear");//clear lists and generate new ones to work from
70 ProcessLastPeriodVisitors("Year");
71 GenerateNewNoteCard("Year");
72 lastYear = year;
73 lastPeriodsVisitors = []; //clear to keep memory down while not processing
74 totalVisitorsCalculation = 0; //reset total visitors calc to 0 ready for next time
75 monthsOfYearNotecards = [];//change of year has not occured so this is not needed, clear to keep memory use down
76 }//close process new year
77
78 ProcessLastPeriodVisitors(string type)
79 {
80 notecardsToProcess = [];
81 if (type == "DayOfMonth")
82 {
83 list yesterdaysVisitors = todaysVisitors;
84 string visitorsUnique = "*Unique Visitors = " + (string)llGetListLength(yesterdaysVisitors);
85 string visitorsAll = "*All Visitors = " + (string)llGetListLength(yesterdaysVisitors);
86 yesterdaysVisitors += visitorsUnique; //adds the line above to the list
87 yesterdaysVisitors += visitorsAll; //adds the line above to the list
88 if (llGetInventoryType("Yesterday") == INVENTORY_NOTECARD) llRemoveInventory("Yesterday");
89 osMakeNotecard("Yesterday", yesterdaysVisitors); //save the notecard
90 EnsureNotecardWritten("Yesterday");
91 notecardsToProcess += "Yesterday";
92 }
93 else if (type == "MonthOfYear")
94 {
95 notecardsToProcess = daysOfMonthNotecards;
96 daysOfMonthNotecards = []; //clear to keep memory use down
97 }
98 else if (type == "Year")
99 {
100 notecardsToProcess = monthsOfYearNotecards;
101 monthsOfYearNotecards = [];//clear to keep memory down
102 }
103 lastPeriodsVisitors = []; //ensure the list is clear at the start
104 integer numberOfNotecardsToProcess = llGetListLength(notecardsToProcess);
105 integer noteCardIndex;
106 totalVisitorsCalculation = 0;
107 for (noteCardIndex = numberOfNotecardsToProcess-1; noteCardIndex >= 0; noteCardIndex--)
108 {
109 string notecardName = llList2String(notecardsToProcess, noteCardIndex);
110 ProcessVisitorsNotecard(notecardName); //adds contentents to the period list and total visitors figures preventing duplicates in the list
111 llRemoveInventory(notecardName);
112 }
113 }
114
115 ProcessVisitorsNotecard(string notecardName)
116 { //loops through the named notecard, adding the total visitors together and adding new uninque visitors to a period list
117 string currentLine;
118 integer notecardLength = osGetNumberOfNotecardLines(notecardName);
119 integer lineIndex;
120 for (lineIndex = 0; lineIndex < notecardLength; lineIndex++)
121 { //loops through the selected notecard
122 currentLine = osGetNotecardLine(notecardName, lineIndex);
123 string firstTwoChars = llGetSubString(currentLine, 0, 1);
124 if (currentLine != "")
125 {
126 if (firstTwoChars == "*A" || firstTwoChars == "*U") //process this line as a total for notecard
127 { //do this the long way, assume people are idiots and manually change an auto generated notecard.
128 if (firstTwoChars == "*A")
129 { //only process the all figures when adding together.
130 integer equalsIndex = llSubStringIndex (currentLine, "="); //get the position of the equals sign
131 string strVisitors = llGetSubString(currentLine, equalsIndex+1, -1); //everything after the equals sign
132 strVisitors = llStringTrim(strVisitors, STRING_TRIM); //remove any white space
133 integer visitors = (integer) strVisitors; //convert to an integer
134 totalVisitorsCalculation += visitors; //add value to total visitors calc figure
135 } //close if first two charas are *A
136 }//close if first char is an *
137 else
138 {
139 if (!(~llListFindList(lastPeriodsVisitors, (list)currentLine)))
140 { //if this visitor is not the last periods list add them
141 currentLine = osGetNotecardLine(notecardName, lineIndex);
142 lastPeriodsVisitors += currentLine;
143 }//close if not on list
144 }//close if line does not start with an asterix
145 }//close if line is not blank
146 }//close loop through notecard
147 }//close process visitors notecard
148
149 GenerateNewNoteCard(string notecardType)
150 { //saves yesterdays vistors, clears the lists and sets last day to todays day ;
151 integer lastTimePeriod;
152 if (notecardType == "DayOfMonth") lastTimePeriod = lastDay;
153 else if (notecardType == "MonthOfYear") lastTimePeriod = lastMonth;
154 else if (notecardType == "Year") lastTimePeriod = lastYear;
155 string visitorsUnique = "*Unique Visitors = " + (string)llGetListLength(lastPeriodsVisitors);
156 string visitorsAll = "*All Visitors = " + (string)totalVisitorsCalculation;
157 lastPeriodsVisitors += visitorsUnique; //adds the line above to the list
158 lastPeriodsVisitors += visitorsAll; //adds the line above to the list
159 string tail;
160 if (lastTimePeriod < 10) tail = "0" + (string)lastTimePeriod; //keep the tail to always be 2 characters
161 else tail = (string)lastTimePeriod; //set the tail string based on the day of the month yesterday
162 string notecardName = notecardType + "-" + tail;
163 if (llGetInventoryType(notecardName) == INVENTORY_NOTECARD) llRemoveInventory(notecardName);
164 osMakeNotecard(notecardName, lastPeriodsVisitors); //save the notecard
165 EnsureNotecardWritten(notecardName);
166 lastPeriodsVisitors = [];
167 }//close process new day
168
169 PopulateDaysAndMonthsNoteardLists(string callingMethod)
170 { //goes through the inventory making lists of the notecard names for days of the month and months of the year
171 daysOfMonthNotecards = []; //ensure the list starts empty
172 monthsOfYearNotecards = []; //ensure the list starts empty
173 integer totalNotecards = llGetInventoryNumber(INVENTORY_NOTECARD);
174 integer notecardIndex;
175 for (notecardIndex = 0; notecardIndex < totalNotecards; notecardIndex++)
176 { //loops through all notecards and makes a list of the day of the month notecards
177 string notecardName = llGetInventoryName(INVENTORY_NOTECARD, notecardIndex);
178 integer hyphenIndex = llSubStringIndex(notecardName, "-");
179 if (hyphenIndex >= 0)
180 { //only come here if the name contains a hypen, otherwise ignore as its not part of the system
181 string notecardType = llGetSubString(notecardName, 0, hyphenIndex-1); //everything before the hypen
182 if (notecardType == "DayOfMonth")
183 {
184 daysOfMonthNotecards += notecardName; //add this card to the days of the month list
185 }
186 else if (notecardType == "MonthOfYear")
187 {
188 monthsOfYearNotecards += notecardName; //add this card to the months of the year list
189 }
190 //no else as its not part of the system so gets ignored
191 }//close if its a notecard belonging to the ones we need to processs
192 }//close loop through all notecards
193 }//populate days and months lists.
194
195 string ParseName(string detectedName)
196 { // parse name so both local and hg visitors are displayed nicely
197 //hypergrid name example firstName.LastName@SomeGrid.com:8002
198 string firstName;
199 string lastName;
200 string cleanName;
201 integer atIndex = llSubStringIndex(detectedName, "@"); //get the index position of the "@" symbol if present
202 integer periodIndex = llSubStringIndex(detectedName, ".");//get the index position of the "." if present
203 list nameSegments;
204 if ((periodIndex >= 0) && (atIndex >= 0))
205 { //the detected name contains both an "@"" and "." so this avi is a hypergrid visitor
206 nameSegments = llParseString2List(detectedName,[" "],["@"]);//split the dected name into two list elements
207 string hGGridName = llList2String(nameSegments,0); //everything before the @
208 nameSegments = llParseStringKeepNulls(hGGridName, [" "], ["."]); //split the hg name into two list elements
209 firstName = llList2String(nameSegments,0); //retrieve the first name from the 1st index in the list
210 lastName = llList2String(nameSegments,2); //retrieve the last name form the 2nd index in the list
211 cleanName = firstName + " " + lastName; //combines the names to look like a local visitors name
212 }//close if hg visitor
213 else
214 { //this is a local visitor the name is already clean
215 cleanName = detectedName;
216 }//close if local visitor
217 return cleanName; //returns the cleaned name to the calling method
218 }//close parse name
219
220 SetUpListeners()
221 {//sets the coms channel and the random menu channel then turns the listeners on.
222 menuChannel = (integer)(llFrand(-1000000000.0) - 1000000000.0); //generates random main menu channel
223 menuChannelListen = llListen(menuChannel, "", NULL_KEY, "");//sets up main menu listen integer
224 llListenControl (menuChannelListen, FALSE); //turns off listeners for main menu channel
225 }//close set up listeners
226
227 DialogAdminMenu(key aviUUID)
228 { //deliver the menu to the admin provided
229 list buttons = ["Visitors", "Done"]; //list of buttons on the menu
230 string message = "Will deliver a folder with the visitors details in it."; //message on the menu
231 llDialog(aviUUID, message, buttons, menuChannel); //delivers the actual menu
232 }//close deliver dialog menu
233
234 ShowVisitors (key aviUUID)
235 { //adds an extra card to show todays visitors then delivers a folder of all visitor details.
236 list notecardToMake = todaysVisitors;
237 integer numberOfVisitorsToday = llGetListLength(notecardToMake);
238 string notecardName = "Todays-Visitors";
239 string visitorsUnique = "*Unique Visitors = " + (string)numberOfVisitorsToday;
240 string visitorsAll = "*All Visitors = " + (string)numberOfVisitorsToday;
241 notecardToMake += visitorsUnique; //adds the line above to the list
242 notecardToMake += visitorsAll; //adds the line above to the list
243 if (llGetInventoryType(notecardName) != -1)
244 { //if this notecard already exists delete it
245 llRemoveInventory(notecardName);
246 }//close if notecard already exists
247 osMakeNotecard(notecardName, notecardToMake); //save the notecard
248 list itemsToDeliver = [];
249 integer notecardIndex;
250 for (notecardIndex = 0; notecardIndex < llGetInventoryNumber(INVENTORY_NOTECARD); notecardIndex++)
251 { //loops through all notecards in the inventory.
252 string notecardToProcess = llGetInventoryName(INVENTORY_NOTECARD, notecardIndex);
253 integer hyphenIndex = llSubStringIndex(notecardToProcess, "-");
254 if (hyphenIndex != -1)
255 { //ignore all notecards which do not have a hyphen in them
256 string notecardType = llGetSubString(notecardToProcess, 0, hyphenIndex-1);
257 if (notecardType == "DayOfMonth" || notecardType == "MonthOfYear" || notecardType == "Year" || notecardType == "Todays")
258 { //only process notecards starting with "DayOfMonth, MonthOfYear or Year
259 itemsToDeliver += notecardToProcess;
260 }//close if name matechs our criteria
261 }//close if there is a hypen
262 }//close loop through all notecards in the inventory.
263 llGiveInventoryList(aviUUID, llGetObjectName(), itemsToDeliver);
264 llListenControl (menuChannelListen, FALSE); //turns off listeners for main menu channel
265 menuListen = FALSE;
266 llRemoveInventory(notecardName);
267 CleanTodaysVisitorsList(); //clean up pass by reference mess
268 }//close show visitors.
269
270 CleanTodaysVisitorsList()
271 { //this list is passed by refernece earlier, either we clean it now or we do a loop copy earlier
272 integer index = llGetListLength(todaysVisitors)-1;
273 for (; index >=0; index--)
274 {
275 string toTest = llList2String(todaysVisitors,index);
276 if (llGetSubString(toTest,0,0) == "*")
277 { //removes unique visitos and all visitors lines which get added earlier.
278 todaysVisitors = llDeleteSubList(todaysVisitors, index,index);
279 }
280 }
281 }//close clean todays visitors list.
282
283 ProcessInstructionLine(string instruction, string data, string notecardName)
284 { //we only need the data, add it to the admins list
285 if (notecardName == "Admin")
286 {
287 if (!(~llListFindList(admins, (list)data)))
288 {
289 admins += data;
290 }
291 }
292 else if (notecardName == "Ignore")
293 {
294 if (!(~llListFindList(ignore, (list)data)))
295 {
296 ignore +=data;
297 }
298 }
299 }//close process instruction line
300
301 string CleanUpString(string inputString)
302 { //takes in the string provided by the sending method, removes white space and converts it to lower case then returns the string to the sending method
303 string cleanString = llStringTrim( llToLower(inputString), STRING_TRIM ); //does the clean up
304 return cleanString; //returns the string to the sending method now its cleaned up
305 }//close clean up string.
306
307 ReadConfigCards(string notecardName)
308 { //Reads the named config card if it exists
309 if (llGetInventoryType(notecardName) == INVENTORY_NOTECARD)
310 { //only come here if the name notecard actually exists, otherwise give the user an error
311 integer notecardLength = osGetNumberOfNotecardLines(notecardName); //gets the length of the notecard
312 integer index; //defines the index for the next line
313 for (index = 0; index < notecardLength; ++index)
314 { //loops through the notecard line by line
315 string currentLine = osGetNotecardLine(notecardName,index); //contents of the current line exactly as it is in the notecard
316 string firstChar = llGetSubString(currentLine, 0,0); //gets the first character of this line
317 integer equalsIndex = llSubStringIndex(currentLine, "="); //gets the position of hte equals sign on this line if it exists
318 if (currentLine != "" && firstChar != "#" && equalsIndex != -1 )
319 { //only come here if the line has content, it does not start with # and it contains an equal sign
320 string instruction = llGetSubString (currentLine, 0, equalsIndex-1); //everything before the equals sign
321 string data = llGetSubString(currentLine, equalsIndex+1, -1); //everything after the equals sign
322 instruction = CleanUpString (instruction); //sends the instruvtion to the cleanup method to remove white space and turn to lower case
323 data = CleanUpString (data); //sends the data to the cleanup method to remove white space and turn to lower case
324 ProcessInstructionLine(instruction, data, notecardName); //sends the instruction and the data to the Process instruction method
325 }//close if the line is valid
326 else
327 { //come here if the above condition is not met
328 if ( (currentLine != "") && (firstChar != "#") && (equalsIndex == -1))
329 { // if the line is not blank and it does not begin with a #, and there is no = sign send an error telling the user which line is invalid.
330 llOwnerSay("Line number: " + (string)index + " is malformed. It is not blank, and does not begin with a #, yet it contains no equals sign.");
331 }//close line is invalid
332 }//close invalid line
333 }
334 }//close if the notecard exists
335 else
336 { //the named notecard does not exist, send an error to the user.
337 //llOwnerSay ("The notecard called " + notecardName + " is missing, auto generating one with just the owner added");
338 GenerateMissingConfigCard(notecardName);
339
340 }//close error the notecard does not exist
341 }//close read config card.
342
343 GenerateMissingConfigCard(string notecardName)
344 {
345 string dataToAdd = notecardName + " = " + (string)llGetOwner();
346 string title = "# " + notecardName + "'s" ;
347 list newNotecardContents = [title, dataToAdd];
348 osMakeNotecard(notecardName, newNotecardContents); //save the notecard
349 }
350
351 ProcessDetectedAvatars()
352 { //processes avatars detected by either the region list or collission event.
353 list avatarsInRegion = llGetAgentList(AGENT_LIST_REGION, []); //generates a list of all avatar uuids in the region
354 integer avatarIndex;
355 for (avatarIndex = 0; avatarIndex < llGetListLength(avatarsInRegion); avatarIndex++)
356 { //loop through all detected avis
357 key uuidToCheck = llList2Key(avatarsInRegion, avatarIndex); //avi we are currently dealing with
358 string aviName = llKey2Name(uuidToCheck);
359 string cleanName = ParseName (aviName); //get avi name without hg stuff if present
360 if (llDetectedType(avatarIndex) != 0)
361 {
362 if (!(~llListFindList(ignore, (list)uuidToCheck)))
363 { //if the avi is not on the ignore list come here
364 if (debug) llOwnerSay("Debug:ProcessDetectedAvis: " + uuidToCheck + " is not on the ignore list");
365 if (!(~llListFindList(todaysVisitorsUUIDs, (list)uuidToCheck)))
366 { //if avi has not already visited today add them to both daily visitors and UUID lists
367 todaysVisitorsUUIDs += uuidToCheck; //add this uuid to the list of visitors today, has to be uuid as names could match with hg visitors
368 string homeUri = osGetAvatarHomeURI(uuidToCheck);//get the avatars home grid
369 string newVisitor = cleanName + "," + homeUri; //this is the line we add to the visitors list
370 todaysVisitors += newVisitor;//add the line abive to todays visitors list.
371 llMessageLinked(LINK_THIS, 93827334, uuidToCheck, NULL_KEY); //linked message to helpers
372 llRegionSay(displayComsChannel, uuidToCheck);
373 if (debug) llOwnerSay("Debug:ProcessDetectedAvatars:" + newVisitor + "added to todays visitors list");
374 }//close if not on the list already
375 }
376 }
377
378 }//close loop through detected list
379 }//close process avatars in region
380
381 EnsureNotecardWritten(string notecardName)
382 { //holds the scrit in a loop untill the card is written
383 integer notecardWritten = FALSE;
384 while (!notecardWritten)
385 { //if the status is not written come here
386 if (llGetInventoryType(notecardName) == INVENTORY_NOTECARD) notecardWritten = TRUE; //change to true if its written
387 } //close while not written
388 }//close ensure notecard is written.
389
390 default
391 {
392 changed( integer change )
393 { //if we have been moved to a new region or changed owne reset the script
394 if (change & (CHANGED_OWNER | CHANGED_REGION)) llResetScript();
395 }//close changed
396
397 state_entry()
398 {
399 osVolumeDetect(TRUE); //makes item volumetric
400 SetUpListeners();
401 //start fake test data
402 //==========================
403 //lastYear = 2018;
404 //lastMonth = 11;
405 //lastDay = 22;
406 //==========================
407 //end fake test data
408 lastYear = GetDate("Year");
409 lastMonth = GetDate("Month");
410 lastDay = GetDate("Day");
411 ReadConfigCards("Admin");
412 ReadConfigCards("Ignore");
413 llSetTimerEvent(timeInterval); //every 30 mins
414 }//close state entry
415
416 collision_start(integer total_number)
417 {
418 integer colliderIndex = 0;
419 for (colliderIndex; colliderIndex < total_number; colliderIndex++)
420 {
421 integer detectedType = llDetectedType(colliderIndex);
422 if (detectedType == 1 || detectedType == 3 || detectedType == 5)
423 { //only process avatars, no bots or physical objects
424 key detectedUUID = llDetectedKey(colliderIndex);
425 if (detectedUUID != lastCollider)
426 { //if this is the same avi just standing on the dector don't process them
427 lastCollider = detectedUUID;
428 ProcessDetectedAvatars();
429 }//close if not last collider
430 }//close if detected type is an avatar
431 }
432 }//close collision event
433
434 touch_start(integer num_detected)
435 { //come here any time the object is clicked
436 admins = [];
437 ReadConfigCards("Admin");
438 integer detectedIndex = 0;
439 key toucher = llDetectedKey(0);
440 if (~llListFindList(admins, (list)toucher))
441 { //if the toucher is on the admin list deliver the menu
442 lastAdmin = toucher; //store the last admin toucher incase of a time out.
443 llListenControl (menuChannelListen, TRUE); //turns on listeners for main menu channel
444 menuListen = TRUE;
445 DialogAdminMenu(toucher);
446 }//close if toucher is on list
447 //else llRegionSayTo(toucher, PUBLIC_CHANNEL, "Sorry you are not on the admin list and can not use this item.");
448 }//close touch start event
449
450 listen( integer channel, string name, key id, string message )
451 {
452 if (channel == menuChannel)
453 { //come here if the channel is the menu channel
454 if (~llListFindList(admins, (list)id))
455 { //if avi sending the message is on the admins list send them the menu
456 if (message == "Visitors") ShowVisitors(id);
457 }//close if found on admins list
458 }//close channel is the menu channel
459 }//close listen
460
461 timer()
462 { //come here based on the timer event time
463 if (menuListen)
464 { //come here if the menu listener is on
465 menuListen = FALSE;//set listener tracker to false
466 llRegionSayTo(lastAdmin, PUBLIC_CHANNEL, "Menu timed out, please click again"); //warn the last user
467 llListenControl (menuChannelListen, FALSE); //turns on listeners for main menu channel
468 }//close if menu listener is on
469 ProcessDetectedAvatars(); //scan the sim and process all found avis
470 CheckDate(); //check the date to see if its a new day, if it is process the changes (includes month/year if they also changed)
471 }//close timer
472 }//close state default
Admin Notecard Sample
1 # Allowed Admins
2 Admin = 833a98e7-4574-4f07-9580-b06784759411
3 Admin = 8dbc01dc-71c8-4d88-b776-8b8e827d745c
4 Admin = cbd17d01-4a7e-437a-ac57-0c8313508aae
Ignore Notecard Sample
1 # Ignore's
2 Ignore = 833a98e7-4574-4f07-9580-b06784759411
3 Ignore = cbd17d01-4a7e-437a-ac57-0c8313508aae
4 Ignore = 8dbc01dc-71c8-4d88-b776-8b8e827d745c
Syntax Highlighting
GeShi syntax highlighting is enabled on this wiki. <be>
When using the tabs described in the link, change the language part to "lsl". Eg.
syntaxhighlight lang="lsl" line
inside angled brackets <>