User:Cow Taurog/Prim owner board

From Second Life Wiki
< User:Cow Taurog
Revision as of 03:09, 22 April 2014 by Cow Taurog (talk | contribs) (Created page with "__NOTOC__ ==Prim poller== <source lang="lsl"> // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. // To view a copy of …")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Prim poller

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

Hovertext prim owner display

// 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=[];
    }}
}

Xyzzy text prim owner display

// 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=[];
    }}
}

Prim tracker

// 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=[];
    }}
}

Cager finder

// 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.
// 
//Bounding box: <-3.659322, -3.659323, -2.942255>, <3.659322, 3.659322, 2.992700>
//Prim count: 2
//
//[22:35] Cager finder: Bounding box: <-3.659322, -3.659323, -2.942255>, <3.659322, 3.659322, 2.992700>
//Prim count: 2
//
//[22:35] Cager finder: Bounding box: <-1.321905, -1.321905, -1.606233>, <1.321905, 1.321905, 1.566233>
//Prim count: 3
string gsTarget=">:)"; // Name of the object to seek
integer giPrimCount=3; // How many prims the object is
integer giType; // Type of object
float gfMass=19.712570; // Mass of object
//float gfMassTol=0.1; // Mass tolerance
list glIdiots; // Idiot list
list glBound=[<-1.321905,-1.321905,-1.606233>,<1.321905,1.321905,1.566233>]; // Bounding box
//vector gvBoundTol=0.15; // Tolerance of bounding box
float gfRange=96.0; // Range of sensor
float gfPoll=2; // How often to poll
default{
    on_rez(integer param){llResetScript();}
    changed(integer change){if(change&CHANGED_OWNER){llResetScript();}}
    state_entry(){
        giType=ACTIVE|PASSIVE;
        llSetText("",<0.8,0.8,0.8>,1);
        llSensorRepeat(gsTarget,"",giType,gfRange,PI,gfPoll);
    }
    sensor(integer num){integer i;for(i=0;i<num;i++){
        string sM;
        sM=sM+"Bounding box: "+llList2CSV(llGetBoundingBox(llDetectedKey(i)))+"\n";
        sM=sM+"Prim count: "+(string)llGetObjectPrimCount(llDetectedKey(i))+"\n";
        llOwnerSay(sM);
        //llSetText(sM,<0.8,0.8,0.8>,1);
        if(llGetObjectPrimCount(llDetectedKey(i))==giPrimCount){
            llOwnerSay("Prim count");
        if(gfMass==llGetObjectMass(llDetectedKey(i))){
            
        //if(llGetBoundingBox(llDetectedKey(i))==glBound){
            key kO=llDetectedOwner(i);
            if(llListFindList(glIdiots,[kO])==-1){glIdiots=glIdiots+[kO];}
        }}//}
    }}
    touch_start(integer num){if(llDetectedKey(num-1)==llGetOwner()){
        llOwnerSay("Idiots: "+llList2CSV(glIdiots));
    }}
}

Info Fetcher

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

Template:MP