Difference between revisions of "User:Cow Taurog/Prim owner board"

From Second Life Wiki
Jump to navigation Jump to search
 
Line 380: Line 380:


==Prim tracker==
==Prim tracker==
<source lang="lsl">
<lsl>
// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
// To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to

Latest revision as of 03:21, 22 April 2014

Prim poller

<lsl> // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to // Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. // // Cow Taurog's prim owner info fetcher // Last edited on 08/27/2010 // // This script will grab a list of people that have prims on the parcel, prim count, and online status. // The list will be sorted by descending prim count, and their names resolved, then sent over chat and/or link message. // You can use the output provided in your own script, or drop in the display scripts. // // This will not work if you aren't in the same sim unless: // -The land is owned by a group, not an individual. // -This object is deeded to (owned by) the group, not an individual. // You will need to set full perms, and share with the group if you want to be able to edit // the server once it is deeded. You will also need to share with group again after it is deeded. // Group names cannot be resolved from their key, so any group owned objects will show as unknown. // This whole "not working when the owner is gone" thing is why we need this to act by itself as a server.

// -Settings-

float gfPoll=90; // How often to update in seconds. Depends on how fast the display you will use refreshes.

integer giLinkMsgChan=43; // Channel to output the data over link message on (0 to disable).

integer giChatChan=643; // Channel to output the data over chat on (0 to disable).

// The data is output as a pipe seperated list of the key, name, prim count, and presence of all prim owners. // The parcel key is the first item in the list, useful for making sure we get the right info. // <parcel key>|<owner1 key>|<owner1 name>|<owner1 primcount>|<owner1 in sim (1/0)>|<owner2 key>...

list glExcludeKeys=["38429ab1-2d0a-4535-962f-a909cee910e0","83b1a9ee-d1fa-1e11-486c-1aa470872db5"]; // You can choose to exclude any person or group from being shown on the list. I have myself and my group in this list.

float gfDataTimeout=3.0; // How long before giving up on response from the name resolution (owner is a group or <1 day old)

// // There are no more settings past this line. //

list glRaw; // Stores raw data so we can sort and add to it key gkAct; // Target's key integer giCount; // Target's prim count integer giRawLen; // Length of the raw data list integer giExcLen; // Length of the key exclusion list list glData; // Sorted and completed data integer i; // Counter integer k; // Counter key gkReq; // Dataserver request handle integer DEBUG=0; // Debug level. 0=none, 1=minimal, 2-verbose key gkDebugTo=""; // Key to IM debug messages to. Blank to disable. debug2(string mess){if(DEBUG==2){if(gkDebugTo==""){llInstantMessage(gkDebugTo,"Debug: "+mess);}}} // Verbose debug function debug1(string mess){if(DEBUG>0){if(gkDebugTo==""){llInstantMessage(gkDebugTo,"Debug: "+mess);}}} // Minimal debug function default{

   on_rez(integer param){llResetScript();} //Reset when rezzed
   changed(integer change){if(change&CHANGED_OWNER){llResetScript();}} // Reset when owner changes
   state_entry(){
       glData=[]; // Clear data from the last run
       glRaw=llGetParcelPrimOwners(llGetPos()); // Get keys and prim counts from the parcel
       giRawLen=llGetListLength(glRaw); // Calculate length of the raw data
       giExcLen=llGetListLength(glExcludeKeys); // Calculate length of the exclusion list
       debug1("glRaw: "+llList2CSV(glRaw));
       // Remove anyone on the exclusion list
       for(i=0;i<giExcLen;i++){ // Check every entry in the exclusion list
           string sF=llList2String(glExcludeKeys,i); // Store target key
           debug2("sF: "+sF);
           integer iAt=llListFindList(glRaw,[(key)sF]); // Store location of target key
           debug2("iAt: "+(string)iAt);
           if(iAt!=-1){ glRaw=llDeleteSubList(glRaw,iAt,iAt+1);} // If the target is in the list, remove it
       }
       debug2("glRaw after exclusion: "+llList2CSV(glRaw));
       // We can only sort by the first item in a strided list, so we need to reverse the list.
       // Put the prim count first, and make sure it is casted as an integer instead of a string.
       for(i=0;i<giRawLen;i=i+2){ // Loop through the entire list (stride of 2, note the i=i+2 instead of i++)
           integer iCount=llList2Integer(glRaw,i+1); // Store prim count as integer to ensure proper typecasting
           string sOwner=llList2String(glRaw,i); // Store owner key
           glData=glData+[iCount,sOwner]; // Add these to the new data list in reverse order
       }
       // Sort the data by prim count
       integer iDL=llGetListLength(glData)-4; // There is one blank stride on the list for some reason, note the -4.
       debug2("glData before chop: "+llList2CSV(glData));
       glData=llDeleteSubList(glData,iDL,-1); // Chop off the extra entry
       debug2("glData before sort: "+llList2CSV(glData));
       glRaw=[]; // Blank out the raw info from earlier, we don't need it
       glRaw=llListSort(glData,2,FALSE); // Sort data and store it into the empty list
       glData=[]; // Blank out the data we just sorted from
       debug2("glRaw after sort: "+llList2CSV(glRaw));
       i=0; // Set i to zero so we can use it
       // The script now has a sorted list of keys and prim counts. We now resolve their names, and find if they are here
       // We will toggle back and forth between two identical states to resolve the names from the dataserver.
       state fillA; // Go to the first state
   }

} state fillA{

   on_rez(integer param){llResetScript();}
   changed(integer change){if(change&CHANGED_OWNER){llResetScript();}}
   timer(){ // If the timer event is triggered, the name could not be found, either it is a group or <1 day old.
       debug1("Timeout.");
       glData=glData+[gkAct,"(unknown)",giCount,1]; // Store their info into the final list
       i=i+2; // Increment i by 2 since the list is strided
       if(i+4<giRawLen){state fillB;} // If there is is still more to resolve, go to the next state
       else{debug2("show");state show;} // Otherwise finish and show the results
   }
   state_entry(){
       llSetTimerEvent(gfDataTimeout); // Set request timeout
       gkAct=llList2Key(glRaw,i+1); // Store target's key (these are global since they are used in dataserver too)
       giCount=llList2Integer(glRaw,i); // Store target's prim count
       gkReq=llRequestAgentData(gkAct,DATA_NAME);  // Request the name from the dataserver
       debug2("Requested (A)");
   }
   dataserver(key req,string mess){if(req==gkReq){ // Make sure this is our request, and not some random one
       llSetTimerEvent(0); // Keep the timeout event from triggering since we got our result
       debug2("Dataserver (A): "+mess);
       vector vO=llGetAgentSize(gkAct); // Store the target's size (will be <0,0,0> if they are a group, or aren't in the sim)
       if(vO!=ZERO_VECTOR){glData=glData+[gkAct,mess,giCount,1];} // Put their info into the final list, and a 1 for presence
       else{glData=glData+[gkAct,mess,giCount,0];} // Put their info into the final list, and a 0 for presence
       llSleep(0.1); // Wait for a tiny bit to prevent weirdness
       i=i+2; // Increment i by 2 to advance to the next entry
       if(i+4<giRawLen){state fillB;} // If there is still more to resolve, go to the next state
       else{debug2("show");state show;} // Otherwise finish and show the results
   }}

} state fillB{ // Second verse, same as the first. Only this one goes to state fillA instead.

   on_rez(integer param){llResetScript();}
   changed(integer change){if(change&CHANGED_OWNER){llResetScript();}}
   timer(){
       debug1("Timeout.");
       glData=glData+[gkAct,"(unknown)",giCount,1];
       llSleep(0.1);
       i=i+2;
       if(i+4<giRawLen){state fillA;}else{debug2("show");state show;}
   }
   state_entry(){
       llSetTimerEvent(gfDataTimeout);
       gkAct=llList2Key(glRaw,i+1);
       giCount=llList2Integer(glRaw,i);
       gkReq=llRequestAgentData(gkAct,DATA_NAME);
       debug2("Requested (B)");
   }
   dataserver(key req,string mess){if(req==gkReq){
       llSetTimerEvent(0);
       debug2("Dataserver (B): "+mess);
       vector vO=llGetAgentSize(gkAct);
       if(vO!=ZERO_VECTOR){glData=glData+[gkAct,mess,giCount,1];}
       else{glData=glData+[gkAct,mess,giCount,0];}
       llSleep(0.1);
       i=i+2;
       if(i+4<giRawLen){state fillA;}else{debug2("show");state show;}
   }}

} state show{

   on_rez(integer param){llResetScript();}
   changed(integer change){if(change&CHANGED_OWNER){llResetScript();}}
   state_entry(){
       llSetTimerEvent(gfPoll); // Start the timer so we can do this all over again
       llListen(giChatChan+1,"","",""); // Listen for a reset message
       debug1("glData: "+llList2CSV(glData));
       string sD=llDumpList2String(glData,"|"); // Dump the whole thing into a string seperated with "|"
       string sI=llList2Key(llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_ID]),0); // Store the parcel key
       if(giLinkMsgChan!=0){llMessageLinked(LINK_SET,giLinkMsgChan,sD,(key)sI);} // Output data on linkmsg
       if(giChatChan!=0){llRegionSay(giChatChan,sI+"|"+sD);debug2((string)giChatChan+": "+sI+"|"+sD);} // Output on chat
   }
   timer(){i=0;glData=[];state default;} // Time to poll again, reset the list and the counter, and start over.
   listen(integer chan,string name,key id,string mess){
       if(llSameGroup(id)==TRUE){if(mess=="refresh"){i=0;glData=[];state default;}} // Refresh if told to
   }

} </lsl>

Hovertext prim owner display

<lsl> // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to // Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. // //This script is meant to provide a easy and fast display that shows the parcel's prim owner info as hovertext. //You can drop this into any object on the parcel. integer giInputChan=643; // Chat channel to listen for data on vector gvColor=<0.3,0.6,1>; // Text color float gfAlpha=1; // Text transparency (0=transparent, 1=opaque) // // There are no more settings past this line. // string gsOutput; // Stores final output key gkParcel; // Stores the parcel's key list glKeys; // Stores prim owner's keys list glNames; // Stores prim owner's names list glCounts; // Stores prim counts list glPresences; // Stores presence status list glRaw; // Stores raw data integer i; // Counter integer DEBUG=0; // Debug level. 0=none, 1=minimal, 2-verbose debug2(string mess){if(DEBUG==2){llOwnerSay("Debug: "+mess);}} // Verbose debug function default{

   on_rez(integer param){llResetScript();}
   changed(integer change){if(change&CHANGED_OWNER){llResetScript();}}
   touch_start(integer num){if(llDetectedKey(num-1)==llGetOwner()){
       llSetText("",gvColor,gfAlpha);llRegionSay(giInputChan+1,"refresh");
   }}
   state_entry(){
       llSetText("",gvColor,gfAlpha);
       gkParcel=llList2Key(llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_ID]),0);
       llListen(giInputChan,"","","");
   }
   listen(integer chan,string name,key id,string mess){if(llSameGroup(id)==TRUE){
       debug2("mess: "+mess);
       glRaw=llParseString2List(mess,["|"],[]);
       debug2("glRaw: "+llList2CSV(glRaw));
       if(llList2Key(glRaw,0)!=gkParcel){state default;}
       glRaw=llDeleteSubList(glRaw,0,0);
       debug2("glRaw after removed parcel: "+llList2CSV(glRaw));
       integer iRawLen=llGetListLength(glRaw);
       for(i=0;i<iRawLen;i=i+4){
           glKeys=glKeys+[llList2Key(glRaw,0)];
           glNames=glNames+[llList2String(glRaw,1)];
           glCounts=glCounts+[llList2Integer(glRaw,2)];
           glPresences=glPresences+[llList2Integer(glRaw,3)];
           glRaw=llDeleteSubList(glRaw,0,3);
           debug2("glRaw entry removal: "+llList2CSV(glRaw));
       }
       glRaw=[];
       debug2("glKeys: "+llList2CSV(glKeys));
       debug2("glNames: "+llList2CSV(glNames));
       debug2("glCounts: "+llList2CSV(glCounts));
       debug2("glPresences: "+llList2CSV(glPresences));
       float fClock=llGetGMTclock();
       integer iHours=((integer)fClock/3600);
       integer iMinutes=((integer)fClock/60)-(iHours*60);
       string sHours=(string)iHours;
       if(iHours<10){sHours="0"+sHours;}
       string sMinutes=(string)iMinutes;
       if(iMinutes<10){sMinutes="0"+sMinutes;}
       gsOutput=
        " Updated "+sHours+sMinutes+"Z\n"+
        (string)(llGetParcelMaxPrims(llGetPos(),1)-llGetParcelPrimCount(llGetPos(),PARCEL_COUNT_TOTAL,1))+
        " prims remain\n";
       for(i=1;i<=llGetListLength(glKeys);i++){
           key kL=(key)((string)i);
           gsOutput=gsOutput+" "+llList2String(glNames,i-1)+" ("+llList2String(glCounts,i-1)+")";
           if(llList2String(glPresences,i-1)=="1"){gsOutput=gsOutput+"\n";}
           else{gsOutput=gsOutput+" (not here)\n";}
       }
       llSetText(gsOutput,gvColor,gfAlpha);
       glKeys=[];
       glNames=[];
       glCounts=[];
       glPresences=[];
   }}

} </lsl>

Xyzzy text prim owner display

<lsl> // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to // Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. // // This script will make a xyzzytext display show info about the prim owners on your parcel. // Drop this and the xyzzy controller into your display, and set the number of lines to match yours. integer giInputChan=643; // Chat channel to listen for data on. integer giScreenRows=10; // Number of rows in your xytext display. vector gvOnColor=<0,0.25,0.5>; // Font color for people who are here. vector gvOffColor=<0.5,0.25,0>; // Font color for people who aren't here. vector gvTextColor=<0,0.25,0>; // Font color for normal text float gfDelay=90; // How often to poll for changes // // There are no more settings past this line. // integer giLinesShown; // Counts number of lines used so we don't have to blank all of them key gkParcel; // Stores the parcel's key list glKeys; // Stores prim owner's keys list glNames; // Stores prim owner's names list glCounts; // Stores prim counts list glPresences; // Stores presence status list glRaw; // Stores raw data integer i; // Counter integer DEBUG=0; // Debug level. 0=none, 1=minimal, 2-verbose debug2(string mess){if(DEBUG==2){llOwnerSay("Debug: "+mess);}} // Verbose debug function default{

   on_rez(integer param){llResetScript();}
   changed(integer change){if(change&CHANGED_OWNER){llResetScript();}}
   touch_start(integer num){if(llDetectedKey(num-1)==llGetOwner()){
       //for(i=0;i<=giLinesShown+2;i++){llMessageLinked(LINK_SET,204000,"",(string)i);}
       llRegionSay(giInputChan+1,"refresh");
       llMessageLinked(LINK_SET,99292,"poll","");
   }}
   //timer(){llMessageLinked(LINK_SET,99292,"poll","");}
   state_entry(){
       giScreenRows++; // Rows start at zero, so add 1 to use normal human numbers
       //llSetTimerEvent(gfDelay);
       llMessageLinked(LINK_SET,204000,"","0");
       llMessageLinked(LINK_SET,204006,(string)gvOnColor,(string)i);
       for(i=4;i<giScreenRows;i++){
           llMessageLinked(LINK_SET,204000,"",(string)i);
           llMessageLinked(LINK_SET,204006,(string)gvOnColor,(string)i);
       }
       //for(i=0;i<giScreenRows;i++){llMessageLinked(LINK_SET,204000,"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",(string)i);}
       gkParcel=llList2Key(llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_ID]),0);
       llListen(giInputChan,"","","");
       llRegionSay(giInputChan+1,"refresh");
       llMessageLinked(LINK_SET,99292,"poll","");
   }
   listen(integer chan,string name,key id,string mess){if(llSameGroup(id)==TRUE){
       debug2("raw mess: "+mess);
       if(llGetSubString(mess,36,-1)=="||(unknown)|0|1"){
           float fClock=llGetGMTclock();
           integer iHours=((integer)fClock/3600);
           integer iMinutes=((integer)fClock/60)-(iHours*60);
           string sHours=(string)iHours;
           if(iHours<10){sHours="0"+sHours;}
           string sMinutes=(string)iMinutes;
           if(iMinutes<10){sMinutes="0"+sMinutes;}
           llMessageLinked(LINK_SET,204000,
           " Updated "+sHours+sMinutes+"Z        "+
           (string)(llGetParcelMaxPrims(llGetPos(),1)-llGetParcelPrimCount(llGetPos(),PARCEL_COUNT_TOTAL,1))+
           " prims remain ","0");
           //for(i=4;i<=giScreenRows;i++){llMessageLinked(LINK_SET,204000,"",(string)i);}
           llMessageLinked(LINK_SET,204006,(string)gvOnColor,"4");
           llMessageLinked(LINK_SET,204000,"* Welcome! No prims are in use","4");  
       }else{
           debug2("mess: "+mess);
           glRaw=llParseString2List(mess,["|"],[]);
           debug2("glRaw: "+llList2CSV(glRaw));
           if(llList2Key(glRaw,0)!=gkParcel){state default;}
           glRaw=llDeleteSubList(glRaw,0,0);
           debug2("glRaw after removed parcel: "+llList2CSV(glRaw));
           integer iRawLen=llGetListLength(glRaw);
           for(i=0;i<iRawLen;i=i+4){
               glKeys=glKeys+[llList2Key(glRaw,0)];
               glNames=glNames+[llList2String(glRaw,1)];
               glCounts=glCounts+[llList2Integer(glRaw,2)];
               glPresences=glPresences+[llList2Integer(glRaw,3)];
               glRaw=llDeleteSubList(glRaw,0,3);
               debug2("glRaw entry removal: "+llList2CSV(glRaw));
           }
           giLinesShown=llGetListLength(glKeys);
           for(i=4;i<=giLinesShown+1;i++){llMessageLinked(LINK_SET,204000,"",(string)i);}
           glRaw=[];
           debug2("glKeys: "+llList2CSV(glKeys));
           debug2("glNames: "+llList2CSV(glNames));
           debug2("glCounts: "+llList2CSV(glCounts));
           debug2("glPresences: "+llList2CSV(glPresences));
           float fClock=llGetGMTclock();
           integer iHours=((integer)fClock/3600);
           integer iMinutes=((integer)fClock/60)-(iHours*60);
           string sHours=(string)iHours;
           if(iHours<10){sHours="0"+sHours;}
           string sMinutes=(string)iMinutes;
           if(iMinutes<10){sMinutes="0"+sMinutes;}
           llMessageLinked(LINK_SET,204000,
            " Updated "+sHours+sMinutes+"Z        "+
            (string)(llGetParcelMaxPrims(llGetPos(),1)-llGetParcelPrimCount(llGetPos(),PARCEL_COUNT_TOTAL,1))+
            " prims remain ","0");
           for(i=4;i<giScreenRows;i++){
               string sM;
               sM=" "+llList2String(glNames,i-4)+" ("+llList2String(glCounts,i-4)+")";
               debug2("sM: "+sM);
               if(llList2String(glKeys,i-4)!=""){
                   if(llList2Integer(glPresences,i)==0){
                       sM=sM+" (not here)";
                       llMessageLinked(LINK_SET,204006,(string)gvOffColor,(key)((string)i));
                       llMessageLinked(LINK_SET,204000,sM,(key)((string)i));
                   }else{
                       llMessageLinked(LINK_SET,204006,(string)gvOnColor,(key)((string)i));
                       llMessageLinked(LINK_SET,204000,sM,(key)((string)i));
                   }
               }
           }
       }
       glKeys=[];
       glNames=[];
       glCounts=[];
       glPresences=[];
   }}

} </lsl>

Prim tracker

<lsl> // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to // Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. // // This script will track who rezzes new prims, removes all their prims, and leaves without cleaning up. // integer giInputChan=643; // Chat channel to listen for data on integer giLeftBehindTol=125; // Don't nag someone unless they have more than this // // There are no more settings past this line. // key gkParcel; // Stores the parcel's key list glKeys; // Stores prim owner's keys list glNames; // Stores prim owner's names list glCounts; // Stores prim counts list glPresences; // Stores presence status list glOldKeys; list glOldNames; list glOldCounts; list glOldPresences; list glWarnList; list glRaw; // Stores raw data integer i; // Counter integer DEBUG=0; // Debug level. 0=none, 1=minimal, 2-verbose say(string mess, string hours, string minutes){llOwnerSay(hours+minutes+"Z: "+mess);} debug2(string mess){if(DEBUG==2){llOwnerSay("Debug: "+mess);}} // Verbose debug function debug1(string mess){if(DEBUG>0){llOwnerSay("Debug: "+mess);}} // Minimal debug function default{

   on_rez(integer param){llResetScript();}
   changed(integer change){if(change&CHANGED_OWNER){llResetScript();}}
   touch_start(integer num){if(llDetectedKey(num-1)==llGetOwner()){
       llRegionSay(giInputChan+1,"refresh");
   }}
   state_entry(){
       llSetColor(<1,0,0>,-1);
       gkParcel=llList2Key(llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_ID]),0);
       llListen(giInputChan,"","","");
   }
   listen(integer chan,string name,key id,string mess){if(llSameGroup(id)==TRUE){
       debug2("mess: "+mess);
       glRaw=llParseString2List(mess,["|"],[]);
       debug2("glRaw: "+llList2CSV(glRaw));
       if(llList2Key(glRaw,0)!=gkParcel){state default;}
       glRaw=llDeleteSubList(glRaw,0,0);
       debug2("glRaw after removed parcel: "+llList2CSV(glRaw));
       integer iRawLen=llGetListLength(glRaw);
       for(i=0;i<iRawLen;i=i+4){
           glKeys=glKeys+[llList2Key(glRaw,i)];
           glNames=glNames+[llList2String(glRaw,i+1)];
           glCounts=glCounts+[llList2Integer(glRaw,i+2)];
           glPresences=glPresences+[llList2Integer(glRaw,i+3)];
       }
       glRaw=[];
       debug2("glKeys: "+llList2CSV(glKeys));
       debug2("glNames: "+llList2CSV(glNames));
       debug2("glCounts: "+llList2CSV(glCounts));
       debug2("glPresences: "+llList2CSV(glPresences));
       glOldKeys=glKeys;
       glOldNames=glNames;
       glOldCounts=glCounts;
       glOldPresences=glPresences;
       debug2("glOldKeys: "+llList2CSV(glOldKeys));
       debug2("glOldNames: "+llList2CSV(glOldNames));
       debug2("glOldCounts: "+llList2CSV(glOldCounts));
       debug2("glOldPresences: "+llList2CSV(glOldPresences));
       glKeys=[];
       glNames=[];
       glCounts=[];
       glPresences=[];
       state running;
   }}

} state running{

   on_rez(integer param){llResetScript();}
   changed(integer change){if(change&CHANGED_OWNER){llResetScript();}}
   touch_start(integer num){if(llDetectedKey(num-1)==llGetOwner()){
       llRegionSay(giInputChan+1,"refresh");
   }}
   state_entry(){
       llSetColor(<0,1,0>,-1);
       gkParcel=llList2Key(llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_ID]),0);
       llListen(giInputChan,"","","");
   }
   listen(integer chan,string name,key id,string mess){if(llSameGroup(id)==TRUE){
       debug2("mess: "+mess);
       glRaw=llParseString2List(mess,["|"],[]);
       debug2("glRaw: "+llList2CSV(glRaw));
       if(llList2Key(glRaw,0)!=gkParcel){state running;}
       glRaw=llDeleteSubList(glRaw,0,0);
       debug2("glRaw after removed parcel: "+llList2CSV(glRaw));
       integer iRawLen=llGetListLength(glRaw);
       for(i=0;i<iRawLen;i=i+4){
           glKeys=glKeys+[llList2Key(glRaw,i)];
           glNames=glNames+[llList2String(glRaw,i+1)];
           glCounts=glCounts+[llList2Integer(glRaw,i+2)];
           glPresences=glPresences+[llList2Integer(glRaw,i+3)];
           //glRaw=llDeleteSubList(glRaw,0,3);
           //debug2("glRaw entry removal: "+llList2CSV(glRaw));
       }
       glRaw=[];
       debug2("glKeys: "+llList2CSV(glKeys));
       debug2("glNames: "+llList2CSV(glNames));
       debug2("glCounts: "+llList2CSV(glCounts));
       debug2("glPresences: "+llList2CSV(glPresences));
       debug2("glOldKeys: "+llList2CSV(glOldKeys));
       debug2("glOldNames: "+llList2CSV(glOldNames));
       debug2("glOldCounts: "+llList2CSV(glOldCounts));
       debug2("glOldPresences: "+llList2CSV(glOldPresences));
       float fClock=llGetGMTclock();
       integer iHours=((integer)fClock/3600);
       integer iMinutes=((integer)fClock/60)-(iHours*60);
       string sHours=(string)iHours;
       if(iHours<10){sHours="0"+sHours;}
       string sMinutes=(string)iMinutes;
       if(iMinutes<10){sMinutes="0"+sMinutes;}
       integer iOL=llGetListLength(glOldKeys);
       debug2("iOL: "+(string)iOL);
       integer iKL=llGetListLength(glKeys);
       debug2("iKL: "+(string)iKL);
       for(i=0;i<iKL;i++){
           key kT=llList2Key(glKeys,i);
           string sN=llList2String(glNames,i);
           integer iNC=llList2Integer(glCounts,i);
           integer iOC;
           integer iOCAt=llListFindList(glOldKeys,[kT]);
           if(iOCAt==-1){iOC=-1;}else{iOC=llList2Integer(glOldCounts,iOCAt);}
           integer iNP=llList2Integer(glPresences,i);
           integer iOP;
           integer iOPAt=llListFindList(glOldKeys,[kT]);
           if(iOPAt==-1){iOP=0;}else{iOP=llList2Integer(glOldPresences,iOPAt);}
           debug1("kT: "+(string)kT);
           debug1("sN: "+sN);
           debug1("iNC: "+(string)iNC);
           debug1("iOC: "+(string)iOC);
           debug1("iNP: "+(string)iNP);
           debug1("iOP: "+(string)iOP);
           debug1("\n");
           if(kT!="(unknown)"){if(iOCAt==-1){
               if(iNC==1){say(sN+" rezzed 1 prim.",sHours,sMinutes);}
               else{say(sN+" rezzed "+(string)iNC+" prims.",sHours,sMinutes);}
           }}
           if(iOP==0){if(iNP==1){if(iOPAt!=-1){
               say(sN+" came back.",sHours,sMinutes);
           }}}
           if(iNC>iOC){if(kT!="(unknown)"){
               if(iNC-iOC==1){say(sN+" rezzed 1 more prim.",sHours,sMinutes);}
               else{say(sN+" rezzed "+(string)(iNC-iOC)+" more prims.",sHours,sMinutes);}
           }}
           if(iOC>iNC){if(kT!="(unknown)"){
               if(iOC-iNC==1){say(sN+" removed 1 prim.",sHours,sMinutes);}
               else{say(sN+" removed "+(string)(iOC-iNC)+" prims.",sHours,sMinutes);}
           }}
           if(iOP==1){if(iNP==0){if(kT!="(unknown)"){
               say(sN+" left "+(string)iNC+" prims behind.",sHours,sMinutes);
               if(iNC>giLeftBehindTol){
                   //llInstantMessage(kT,"You have left "+(string)iNC+" prims behind in "+llGetRegionName()+". Please go back and clean up after yourself so other people can use them.");
                   say(sN+" was warned for not cleaning up.",sHours,sMinutes);
               }
           }}}
       }
       for(i=0;i<iKL;i++){
           key kT=llList2Key(glOldKeys,i);
           string sN=llList2String(glOldNames,i);
           integer iOC=llList2Integer(glOldCounts,i);
           integer iNKAt=llListFindList(glKeys,[kT]);
           if(iNKAt==-1){if(iOC>0){if(kT!="(unknown)"){
               say(sN+" removed all "+(string)iOC+" of their prims.",sHours,sMinutes);
           }}}
       }
       glOldKeys=[];
       glOldNames=[];
       glOldCounts=[];
       glOldPresences=[];
       glOldKeys=glKeys;
       glOldNames=glNames;
       glOldCounts=glCounts;
       glOldPresences=glPresences;
       glKeys=[];
       glNames=[];
       glCounts=[];
       glPresences=[];
   }}

} </lsl>

Info Fetcher

<lsl> // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to // Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. // key gkReq; integer giRate; vector gvColor=<0,0.25,0>; default{

   //touch_start(integer num){if(llDetectedKey(0)==llGetOwner()){llResetScript();}}
   state_entry(){
       llMessageLinked(LINK_SET,204006,(string)gvColor,"1");
       llMessageLinked(LINK_SET,204006,(string)gvColor,"2");
       llMessageLinked(LINK_SET,204006,(string)gvColor,"3");
       llMessageLinked(LINK_SET,204000,"","1");
       llMessageLinked(LINK_SET,204000,"","2");
       llMessageLinked(LINK_SET,204000,"","3");
       state poll;
   }

} state poll{

   state_entry(){giRate=0;llSetTimerEvent(60);gkReq=llHTTPRequest("http://secondlife.com/httprequest/homepage.php",[],"");}
   http_response(key req,integer status,list meta,string mess){if(status==200){
       list lT=llParseString2List(mess,["\n"],[]);
       llMessageLinked(LINK_SET,204000,"* Sim population: "+(string)llGetRegionAgentCount(),"1");
       llMessageLinked(LINK_SET,204000,"* Grid population: "+llList2String(lT,17),"2");
       llMessageLinked(LINK_SET,204000,"* Exchange rate: L$"+(string)llRound(llList2Float(lT,11))+" per USD","3");
   }}
   link_message(integer sender,integer num,string mess,key id){if(num==99292){
       if(mess=="poll"){state poll;}
   }}
   timer(){
       giRate++;
       llMessageLinked(LINK_SET,204000,"* Sim population: "+(string)llGetRegionAgentCount(),"1");
       if(giRate>30){state poll;}
   }

} </lsl>