Limitations

Do not rely on this script to give you an incontestable amount of time that an agent spent registered with the system. It is reasonably easy to cheat, if that is the intention. Currently there is no reliable way to track an agent's online status reliably across the grid.

Code: Time Tracker

time_tracker.lsl
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////////
//                   CONFIGURATION                      //
//////////////////////////////////////////////////////////
// API key - can be anything, used as a password.
string API_KEY = "A1364788-B702-4413-B937-7A57E32B43CE";
///////////////////////////////////////////////////////////////////////////
//                              INTERNALS                                //
///////////////////////////////////////////////////////////////////////////
 
list actives = [];
list agents = [];
list times = [];
 
default
{
    state_entry() {
        // ☀ Time Tracker (h:m:s) ☀\n
        // Morgan LeFay - 3
        string text = llList2String(llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT]), 0);
        list split = llParseString2List(text, ["☀ Time Tracker (h:m:s) ☀"], [""]);
        list textTimes = llParseString2List(llList2String(split, 0), ["\n"], [""]);
        if(llGetListLength(textTimes) == 0) jump no_text;
        list displayLine = [];
        do {
            list line = llParseString2List(llList2String(textTimes, 0), [" - "], [""]);
            if(llGetListLength(line) != 2) jump continue;
            agents += llList2String(line, 0);
            // h:m:s
            list time = llParseString2List(llList2String(line, 1), [":"], [""]);
            times += llList2Integer(time, 2) + llList2Integer(time, 1) * 60 + llList2Integer(time, 0) * 3600;
            displayLine += agents + " - " + (string)times;
@continue;
        } while(textTimes = llDeleteSubList(textTimes, 0, 0));
        llSetText("☀ Time Tracker (h:m:s) ☀" + "\n" + llDumpList2String(displayLine, "\n"), <1,1,0>, 1);
@no_text;
        integer comChannel = ((integer)("0x"+llGetSubString(API_KEY,-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
        llListen(comChannel, "[K] Agent Registry", "", "");
        llSetTimerEvent(1);
    }
    listen(integer channel, string name, key id, string message) {
        // B522E348-9F1C-46AF-9D4A-59BFA9668E16#Morgan LeFay|93F8F728-FE99-441A-9BF0-203D835CA3E6#Some Agent
        // set all agents as not active.
        integer itra = llGetListLength(agents)-1;
        do {
            actives = llListReplaceList(actives, (list)0, itra, itra);
        } while(--itra>=0);
        // now we got a fresh set of active agents
        list data = llParseString2List(message, ["|"], [""]);
        do {
            list line = llParseString2List(llList2String(data, 0), ["#"], [""]);
            if(llGetListLength(line) != 2) jump continue;
            string name = llList2String(line, 1);
            integer idx = llListFindList(agents, (list)name);
            // if they're already in the list, set to active and continue;
            if(~idx) {
                actives = llListReplaceList(actives, (list)1, idx, idx);
                jump continue;
            }
            actives += 1; 
            agents += name;
            times += 0;
@continue;
        } while(data = llDeleteSubList(data, 0, 0));
    }
    timer() {
        if(llGetListLength(agents) == 0) return;
        // Add a second to registered agents.
        integer itra = llGetListLength(agents)-1;
        list displayLine = [];
        do {
            integer time = llList2Integer(times, itra);
            // if they're not active, don't increment the timer, but...
            if(llList2Integer(actives, itra) == 0) jump continue;
            times = llListReplaceList(times, (list)(time+1), itra, itra);
            // ...display them.
            integer agentHours = time/3600;
            integer agentMinutes = (time % 3600) / 60;
            integer agentSeconds = (time % 3600) % 60;
            displayLine += llList2String(agents, itra) + " - " + (string)agentHours + ":" + (string)agentMinutes + ":" + (string)agentSeconds;
@continue;
        } while(--itra>=0);
        // Set text.
        llSetText("☀ Time Tracker (h:m:s) ☀" + "\n" + llDumpList2String(displayLine, "\n"), <1,1,0>, 1);
    }
    changed(integer change) {
        if (change & (CHANGED_REGION | CHANGED_REGION_START))
            llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
}