Jump to content

Notify when visitor arrives and leaves area


GloriaGlitter
 Share

You are about to reply to a thread that has been inactive for 120 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I've been looking on MP to purchase a script that will send an IM to a list of admin avatars whenever a visitor arrives in an area and leaves the area.  I did find a free script that purported to do this but it didnt work so I tried hacking it to get it working but wasn't able to fix it.  I did try contacting creator for assistance but since it was free, understandably I couldn't expect any help.  Also since this was someone else's script and was about 290 lines long, I didnt think it fair to post it here for others to help me fix this.   So I have tried starting from scratch looking for snippets of code in the wiki and this forum that I could cobble together.

So far, I have a script that scans the area for visitors and sends an IM to my list of admins.  Thing is it is sending the full list each cycle of the sensor.  I'm trying to find a snippet that can maintain a list of visitors so that I only send an IM to my admins of when someone arrives and later leaves.  I dont need any information about the time they arrived or how long they were there - just that they came and left.

If anyone can point me in the right direction I'd be very grateful.

Link to comment
Share on other sites

I'm not trying to discourage you from trying, but if you have no experience with LSL scripting you will have a hard time writing or modifying a script to meet your specific needs.  You're not asking for something very difficult, but it's not a novice project. I think you'll be better off posting a request in the InWorld Employment forum to attract a scripter who will be willing to write you a custom script.  Be sure to specify that you want the script full perm and you want to have enough comments in it that you will be able to understand how it works.  With that start, you'll have something you can use and can learn from.

Link to comment
Share on other sites

As this is something I've already done myself, here's a simplified version that might help. I hope nothing got mangled in the transcription.

list im_recipients = []; // a list of the keys of the people who will get IMed
float timer_interval = 30.0; // how often to scan the area

list previous_visitors; // a list of the people who were in the area for the last scan, a global value to preserve it between scans

default
{
    state_entry ()
    {
        im_recipients += llGetOwner (); // add yourself on the messaging list.
        llSetTimerEvent (timer_interval); // start the timer (and wait for it to trigger)
    }

    timer ()
    {
        list arrivals;
        list departures;
        list current_visitors = llGetAgentList (AGENT_LIST_PARCEL, []); // get the list of who's here now
        integer count = llGetListLength (current_visitors);
        while (count) // for each current visitor (if any), working backwards through the list (beacuse it's easier)
        {
            key visitor = llList2Key (current_visitors, --count); // decrement the counter (to convert it to a list index, and also set it up for the while loop test next iteration) and get the visitor's key
            if (llListFindList (previous_visitors, [visitor]) == -1) // are they in the list of people who were here last time?
            {
                arrivals += llGetDisplayName (visitor); // if not, add their name to the list of new arrivals
            }
        }
        count = llGetListLength (previous_visitors);
        while (count) // for each visitor who was here last time
        {
            key visitor = llList2Key (previous_visitors, --count);
            if (llListFindList (current_visitors, [visitor]) == -1) // are they still here?
            {
                departures += llGetDisplayName (visitor); // if not, add their name to the list of departures
            }
        }
        string im_message;
        if (arrivals) im_message += "\nArrivals: " + llList2CSV (arrivals); // if there are any new arrivals, add their names, seperated by commas, to the IM message
        if (departures) im_message += "\nDepartures: " + llList2CSV (departures); // if there are any departures, add their names to the message
        if (im_message) // is there anything to report?
        {
            count = llGetListLength (im_recipients);
            while (count) // for each im recipient
            {
                key recipient = llList2Key (im_recipients, --count);
                llInstantMessage (recipient, im_message); // note that this function imposes a 2 second delay on the script and is subject to throttling
            }
        }
        previous_visitors = current_visitors; // save the list of current visitors for next time;
    }
}

But be warned: spamming yourself with IMs, especially if they go to email when you're offline, gets old pretty quickly. As it stands, you may run into issues with the length of the IM text if there's large numbers of people coming and going.

Link to comment
Share on other sites

2 hours ago, KT Kingsley said:

As this is something I've already done myself, here's a simplified version that might help. I hope nothing got mangled in the transcription.

You might want to include list hash checking against llGetAgentList() so you're not needless looping through a list of no changes each cycle.

Also, you might want to add ghost detection checks against agents arriving using llGetAgentSize() and exclude them else you're going to have IMs every cycle of ghosted agents entering then leaving if they are present.

  • Like 1
Link to comment
Share on other sites

Thanks KT - this is just what I was looking for and it works perfectly.  Just one I'd like to change is to limit the llGetAgentList scope to an area defined by a range rather than the whole parcel.  I think this means I need to use llSensor to build the list of agents rather llGetAgentList.  llSensor only returns a single id though so do I need a loop of some sort to build this list?  Thanks.

Link to comment
Share on other sites

So I have changed the llGetAgentList to a sensor to limit the range to 100 mtrs.

Changes I've made to the script above is to:

  • made list current_visitors a global variable
  • added llSensorRepeat to the state-entry
  • added sensor event to build the current_visitor list
  • commented out the llGetAgentList

This almost works but it occasionally misses a departing visitor - shows the text 'Departures' but with no name so I think I have a small error.

I have just posted the top part of the script where I made the changes

 

list im_recipients = []; // a list of the keys of the people who will get IMed
float timer_interval = 30.0; // how often to scan the area

list previous_visitors; // a list of the people who were in the area for the last scan, a global value to preserve it between scans

list current_visitors ;  //made this into global variable

default
{
    state_entry ()
    {
        im_recipients += llGetOwner (); // add yourself on the messaging list.
        llSetTimerEvent (timer_interval); // start the timer (and wait for it to trigger)
        llSensorRepeat("", "", AGENT, 100, PI, 20);  //addded SensorRepeat
    }

 sensor(integer num)
    {  
        integer i;
        current_visitors=[];
        for (i=0; i<num; i++)
        {
            if(llDetectedKey(0) != NULL_KEY)
            {                    
                current_visitors = current_visitors  +llDetectedKey(i) ;
            }
        }
    }

 

    timer ()
    {
        list arrivals;
        list departures;
       // list current_visitors = llGetAgentList (AGENT_LIST_PARCEL, []); // get the list of who's here now - commented out while testing sensor
        integer count = llGetListLength (current_visitors);
        while (count) // for each current visitor (if any), working backwards through the list (beacuse it's easier)
        {
            key visitor = llList2Key (current_visitors, --count); // decrement the counter (to convert it to a list index, and also set it up for the while loop test next iteration) and get the visitor's key

 

Link to comment
Share on other sites

Ah, yes, the departure with no name can happen because llGetDisplayName tries to get the name from the simulator, but that data is deleted from the simulator soon after an avatar leaves the region. One way around that would be to save the names in a list running parallel to the visitors list, another would be to use llRequestDisplayName which queries the database but returns the info in a dataserver event, which would involve extra steps to accommodate.

There's no need to use both the timer and a repeating sensor: you can move the code from the timer event into the sensor event.

Also, remember that when there's no one in sensor range it'll be the no_sensor event that's triggered, not an "empty" sensor event.

Edited by KT Kingsley
Link to comment
Share on other sites

9 hours ago, Lucia Nightfire said:

You might want to include list hash checking against llGetAgentList() so you're not needless looping through a list of no changes each cycle.

Also, you might want to add ghost detection checks against agents arriving using llGetAgentSize() and exclude them else you're going to have IMs every cycle of ghosted agents entering then leaving if they are present.

What would be the best way to generate the hash? Something like string list_hash = llMD5String (llList2CSV (current_visitors), 0);? Or a custom hash, maybe like successively XORing part of the key? (Hmm, I guess MD5 wouldn't work here because the list may have the same contents, but in a different order?)

I don't think I understand the problem with ghosts. Surely once they're detected as being present, they'll continue being detected as present until they are actually exorcised?

Edited by KT Kingsley
Link to comment
Share on other sites

3 hours ago, KT Kingsley said:

What would be the best way to generate the hash? Something like string list_hash = llMD5String (llList2CSV (current_visitors), 0);? Or a custom hash, maybe like successively XORing part of the key? (Hmm, I guess MD5 wouldn't work here because the list may have the same contents, but in a different order?)

I don't think I understand the problem with ghosts. Surely once they're detected as being present, they'll continue being detected as present until they are actually exorcised?

string md5 = "????????????????????????????????";
list AGENTS;
default
{
    state_entry()
    {
        llSetTimerEvent(5.0); //adjust as necessary
    }
    on_rez(integer i)
    {
        llResetScript();
    }
    timer()
    {
        list GAL;
        if ((md5 = llMD5String(llDumpList2String(GAL = llGetAgentList(AGENT_LIST_REGION,[])," "),111)) != md5) //don't bother looping through list if hash hasn't changed
        {
            list GHOSTS;
            key k = NULL_KEY; //because key k; != key k = NULL_KEY;
            integer i;
            integer ii;
            for (i = -llGetListLength(GAL); i < 0; i++)
            {
                if ((ii = (llGetAgentSize(k) != ZERO_VECTOR)) && (llListFindList(AGENTS,[k = llList2Key(GAL,i)]) == -1)) //ghost detection: certain ghosts are seen by llGetAgentList(), one returns NULL_KEY, others a correct agent key, but none are seen by llGetAgentSize()
                {
                    llOwnerSay("secondlife:///app/agent/" + (string)k + "/about entered the region.");
                }
                else if (!ii)
                {
                    GHOSTS = (GHOSTS = []) + GHOSTS + [k]; //yes I still use this method for list defragging / maximum possible memory consumption purposes (its not that important here)
                }
            }
            for (i = -llGetListLength(AGENTS); i < 0; i++)
            {
                if ((llListFindList(GHOSTS,[k]) == -1) && (llGetAgentSize(k = llList2Key(AGENTS,i)) == ZERO_VECTOR)) //counter ghosts continuously reporting leaving every change with llGetAgentList()
                {
                    llOwnerSay("secondlife:///app/agent/" + (string)k + "/about left the region.");
                }
            }
            @out;
            AGENTS = GAL;
        }
        llSetMemoryLimit(65536 - (llGetMemoryLimit() == 65536)); //reallocate memory every cycle (probably necessary if you add more code)
    }
}

Here's a "snippet" you can borrow from.

Link to comment
Share on other sites

Will llMD5String return the same value if llGetAgentList (or llSensorRepeat, which the OP has opted for) return the same keys, but in a different order?

Does llGetAgentList (or llSensorRepeat) sometimes return the same ghost as NULL_KEY and sometimes as the correct key on successive calls?

Also, is memory fragmentation an issue for local list variables? My (probably flawed) understanding is that local variables are created on the stack, and that's cleared when a function or event is completed. I can see how it could cause problems with a global list variable in the heap, though.

Edited by KT Kingsley
Link to comment
Share on other sites

1 hour ago, KT Kingsley said:

Will llMD5String return the same value if llGetAgentList (or llSensorRepeat, which the OP has opted for) return the same keys, but in a different order?

Does llGetAgentList (or llSensorRepeat) sometimes return the same ghost as NULL_KEY and sometimes as the correct key on successive calls?

Also, is memory fragmentation an issue for local list variables? My (probably flawed) understanding is that local variables are created on the stack, and that's cleared when a function or event is completed. I can see how it could cause problems with a global list variable in the heap, though.

Well, I can answer my first question myself here. No.

So because "There is no guaranteed understandable order or randomness to the list returned" by llGetAgentList, and because the sensor will return agents in the order of their proximity – which will change as they move about – you'd have to use some other hash method.

XORing the first eight characters of the key, while simplistic and crude, does seem to work, and would likely be adequate in an application like this. (Bit of an overhead creating the hash in the first place, though.)

default
{
    state_entry ()
    {
        string md5_1 = llMD5String (llList2CSV ([NULL_KEY, llGetOwner (), llGetKey ()]), 1);
        string md5_2 = llMD5String (llList2CSV ([llGetOwner (), llGetKey (), NULL_KEY]), 1);
        llOwnerSay (md5_1);
        llOwnerSay (md5_2);
        llOwnerSay ((string) (md5_1 == md5_2));
        integer hash1 = (integer) ("0x" + llGetSubString ((string) NULL_KEY, 0, 7)) ^ (integer) ("0x" + llGetSubString ((string) llGetOwner (), 0, 7)) ^ (integer) ("0x" + llGetSubString ((string) llGetKey (), 0, 7));
        integer hash2 = (integer) ("0x" + llGetSubString ((string) llGetKey (), 0, 7)) ^ (integer) ("0x" + llGetSubString ((string) llGetOwner (), 0, 7)) ^ (integer) ("0x" + llGetSubString ((string) NULL_KEY, 0, 7));
        llOwnerSay ((string) hash1);
        llOwnerSay ((string) hash2);
        llOwnerSay ((string) (hash1 == hash2));
    }
}

Also, if anyone knows of a ghost avatar anywhere (preferably on a script enabled parcel), could they please let me know. I'd like to experiment with it.

Edited by KT Kingsley
Link to comment
Share on other sites

a way using llGetAgentList in a timer, accepting when a agent is within some distance from the scanner

also shows another way it can be coded to distinguish arrivals and departures, using list add/delete

// global
list prev;

timer()
{
   
   list now = llGetAgentList(...);
   integer n = llGetListLength(now);
   
   // check if avatar is within range
   // if not then delete from now list
   key k;
   vector p = llGetPos();  // position of our scanner
   while(~--n)
   {
      k = llList2Key(now, k);
      // distance between our scanner and the agent
      float d = llVecDist(p, llList2Vector(llGetObjectDetails(k, [OBJECT_POS]), 0);
      if (d > 40.0)
      {  // delete when greater than 40 metres say
         now = llDeleteSubList(now, n, n);
      }
   }         

   list bye;
   if (llGetListLength(now))
   {   
      integer p = llGetListLength(prev);
      while(~--p)
      {
         k = llList2Key(prev, p);
         n = llListFindList(now, [k]));
         if (~n) // is still here
         { // remove from now list
             now = llDeleteSubList(now, n, n);
         }      
         else // is not here now
         {  // add to bye list
            bye += [k];
            // remove from prev list
            prev = llDeleteSubList(prev, p, p);  
         }
      }
   }
   else
   {  // nobody here now
      bye = prev;  
      prev = [];
   }

   // at this point:
   // anybody remaining on now list is a new arrival
   // anybody on bye list has departed
 
   .. send the messages ..
   .. new arrival msg for now list
   .. departure msg for bye list

   // append now to prev for next timer pass
   prev += now;
}

 

swat happens when typing off the top of my head

should be:  k = llList2Key(now, p)  should not be k = llList2Key(now, k)

 

 

 

Edited by Mollymews
Link to comment
Share on other sites

Guys... Don't make it complicated.

Store the avatar keys into a list as people come and go.

Any time you send a message that is supposed to include the avatar's name, just use the URI.

"secondlife:///app/agent/" + (string)avatar_key + "/about" (uses the viewer's setting for names)
"secondlife:///app/agent/" + (string)avatar_key + "/username"
"secondlife:///app/agent/" + (string)avatar_key + "/displayname"
"secondlife:///app/agent/" + (string)avatar_key + "/completename"

The conversion is done by the viewer and doesn't depend on the sim knowing what the key is.

Similarly, if you're creating an integer from a key, you don't need llSubString.

(integer)("0x" + avatar_key) will produce the same result as with llSubString(avatar_key, 0, 7).

Edited by Wulfie Reanimator
  • Like 1
Link to comment
Share on other sites

Will URIs will work with IMs to email? Though I don't know whether the OP wants those or not (I'm expecting a post asking how to stop them sometime soon :)). The (integer)("0x" + avatar_key) is handy to know. Presumably the conversion stops at the first non-hex-digit character that's encountered.

Edited by KT Kingsley
Link to comment
Share on other sites

Thanks for the useful info - I'll work through it as I do need to fix the issue of the missing name for a leaver from the area.  If using the avatars legacy name rather than display name would help solve this then I dont mind that. Regarding the IMs to email, I was looking into using a dataserver event to only send the IMs to my list of admins only if they are online at the time - thought I could combine this with the loop that sends the im to each admin on the list. 

Link to comment
Share on other sites

16 hours ago, KT Kingsley said:

Will URIs will work with IMs to email? Though I don't know whether the OP wants those or not (I'm expecting a post asking how to stop them sometime soon :)). The (integer)("0x" + avatar_key) is handy to know. Presumably the conversion stops at the first non-hex-digit character that's encountered.

The conversion won't work in emails because the email service can't resolve the URI.

Also, I think the hex will only consider up to 8 characters since that will cover all 32 bits. I'm not sure what happens with "0x123-" but I would assume 0, because that's what happens with C's atoi function. That's not really a valid comparison though.

You're right, the conversion stops at the first non-hex digit.

string hex = "0x" + "1-2-3-";
integer i = (integer)hex;
llOwnerSay((string)i);

Depending how many dashes you remove from the string, the result will be 0x1, 0x12, or 0x123.

0x12345678 is a valid integer (as it should be), but 0x123456789 is -1.

Edited by Wulfie Reanimator
  • Thanks 1
Link to comment
Share on other sites

Before I rework the script to be more efficient as has been suggested, I've been trying to incorporate a dataserver event so that I only send the IMs of who has arrived and left to the list of sub-admins only if they are on online, so that their emails are not full of messages about arrivals and departures.  My idea is that my online sub-admins will know who is coming and going and can interact with the visitors if required. 

I am still working on the original posted script to get this bit right before proceeding further but I have a type mismatch in llRequestAgentData which I cant figure out.

--------------------------

list im_recipients =["5b6e2121-5847-4b84-a260-3dd37f4d0d65","2d55c505-9530-40a9-a153-ce3878b0314b"]; // a list of the keys of the people who will get IMed - Gloria, Estella

list previous_visitors; // a list of the people who were in the area for the last scan, a global value to preserve it between scans

list current_visitors ;  //made this into global variable

string data;
integer status;
key owner_key;
string test;

default
{
    state_entry ()
    {
        owner_key =  llGetOwner ();
        im_recipients += owner_key; // add yourself on the messaging list.
        llSetTimerEvent (timer_interval); // start the timer (and wait for it to trigger)
        llSensorRepeat("", "", AGENT, 100, PI, 20);  //addded SensorRepeat
    }
 
 dataserver(key queryid, string data)  
    {
     if ((string)status == queryid)
    test = data;
    }
    
 sensor(integer num)
    {  
        integer i;
        current_visitors=[];
        for (i=0; i<num; i++)
        {
            if(llDetectedKey(0) != NULL_KEY)
            {                    
                current_visitors = current_visitors  +llDetectedKey(i) ;
            }
        }
        list arrivals;
        list departures;
       // list current_visitors = llGetAgentList (AGENT_LIST_PARCEL, []); // get the list of who's here now - commented out while testing sensor
        integer count = llGetListLength (current_visitors);
        while (count) // for each current visitor (if any), working backwards through the list (beacuse it's easier)
        {
            key visitor = llList2Key (current_visitors, --count); // decrement the counter (to convert it to a list index, and also set it up for the while loop test next iteration) and get the visitor's key
            if (llListFindList (previous_visitors, [visitor]) == -1) // are they in the list of people who were here last time?
            {
                arrivals += llGetDisplayName (visitor); // if not, add their name to the list of new arrivals
            }
        }
        count = llGetListLength (previous_visitors);
        while (count) // for each visitor who was here last time
        {
            key visitor = llList2Key (previous_visitors, --count);
            if (llListFindList (current_visitors, [visitor]) == -1) // are they still here?
            {
                departures += llGetDisplayName (visitor); // if not, add their name to the list of departures
            }
        }
        string im_message;
        if (arrivals) im_message += "Arrivals: " + llList2CSV (arrivals); // if there are any new arrivals, add their names, seperated by commas, to the IM message
        if (departures) im_message += "Departures: " + llList2CSV (departures); // if there are any departures, add their names to the message
        if (im_message) // is there anything to report?
        {
            count = llGetListLength (im_recipients);
            while (count) // for each im recipient
            {
                key recipient = llList2Key (im_recipients, --count);
             

             // only send IM if recipient is online
                status = llRequestAgentData(recipient, DATA_ONLINE);
               if (test == 1)
              llInstantMessage (recipient, im_message); // note that this function imposes a 2 second delay on the script and is subject to throttling
            }
        }
        previous_visitors = current_visitors; // save the list of current visitors for next time;
        
    }

 

Link to comment
Share on other sites

It goes something like this:

if (im_message) // is there anything to report?
{
    status_request_count = llGetListLength (im_recipients); // how many recipients?
    im_recipient = llList2Key (im_recipients, --status_request_count); // for the first one, get their key
    status_request_id = llRequestAgentData (im_recipient, DATA_ONLINE); // and find out if they're online
}

Note that the variables being assigned values must be declared globally, so that they are preseved across to the dataserver events.

Then in the dataserver event:

dataserver (key id, string data)
{
    if (id == status_request_id)
    {
        if ((integer) data) llInstantMessage (im_recipient, im_message); // if the recipient is online send the IM
        if (status_request_count) // any more recipients?
        {
            im_recipient = llList2Key (im_recipients, --status_request_count); // if so, get their key
            status_request_id = llRequestAgentData (im_recipient, DATA_ONLINE); // and find out if they're online
        }
    }
}

 

Edited by KT Kingsley
Oops, wrong cast on data
Link to comment
Share on other sites

Thanks KT, very useful - now only those admins that are online get notified of the comings and goings at the place where this script is running.  I just had to declare some variables as global so that the dataserver knew of them

But, I may have broken something when I patched your code in since those online get an initial list of agents in the area and this list is repeatedly sent each time instead of those that have arrived or departed.

Grateful for a once over to see where I might have made an error in incorporating this new piece of code:

-----------------------

 

list im_recipients =["5b6e2121-5847-4b84-a260-3dd37f4d0d65","2d55c505-9530-40a9-a153-ce3878b0314b"]; // a list of the keys of the people who will get IMed - Gloria, Estella

float timer_interval = 30.0; // how often to scan the area

list previous_visitors; // a list of the people who were in the area for the last scan, a global value to preserve it between scans

list current_visitors ;  //made this into global variable

string data;
integer status;

string test;
key status_request_id;
key im_recipient;
string im_message;
integer status_request_count;

default
{
    state_entry ()
    {
       
        im_recipients += llGetOwner (); // add yourself on the messaging list.
      //  llSetTimerEvent (timer_interval); // start the timer (and wait for it to trigger)
        llSensorRepeat("", "", AGENT, 100, PI, 20);  //addded SensorRepeat
        
    }
 
    
 dataserver (key id, string data)
    {
      
       if (id == status_request_id)
       {
         if ((integer) data)  llInstantMessage (im_recipient, im_message); // if the recipient is online send the IM
         if (status_request_count) // any more recipients?
         {
            im_recipient = llList2Key (im_recipients, --status_request_count); // if so, get their key
            status_request_id = llRequestAgentData (im_recipient, DATA_ONLINE); // and find out if they're online
         }
      }
   }
    
    
 sensor(integer num)
    {  
      
        integer i;
        current_visitors=[];
        for (i=0; i<num; i++)
        {
            if(llDetectedKey(0) != NULL_KEY)
            {                    
                current_visitors = current_visitors  +llDetectedKey(i) ;
            }
        }
        list arrivals;
        list departures;
      
        integer count = llGetListLength (current_visitors);
        while (count) // for each current visitor (if any), working backwards through the list (beacuse it's easier)
        {
            key visitor = llList2Key (current_visitors, --count); // decrement the counter (to convert it to a list index, and also set it up for the while loop test next iteration) and get the visitor's key
            if (llListFindList (previous_visitors, [visitor]) == -1) // are they in the list of people who were here last time?
            {
                arrivals += llGetDisplayName (visitor); // if not, add their name to the list of new arrivals
            }
        }
        count = llGetListLength (previous_visitors);
       
        while (count) // for each visitor who was here last time
        {
            key visitor = llList2Key (previous_visitors, --count);
            if (llListFindList (current_visitors, [visitor]) == -1) // are they still here?
            {
                departures += llGetDisplayName (visitor); // if not, add their name to the list of departures
            }
        }
       
       // string im_message;  moved declaration to global because of reference in dataserver


        if (arrivals) im_message += "Arrivals: " + llList2CSV (arrivals) + "\n"; // if there are any new arrivals, add their names, seperated by commas, to the IM message
        if (departures) im_message += "Departures: " + llList2CSV (departures); // if there are any departures, add their names to the message
       
       if (im_message) // is there anything to report?
          {
            status_request_count = llGetListLength (im_recipients); // how many recipients?
            im_recipient = llList2Key (im_recipients, --status_request_count); // for the first one, get their key
           status_request_id = llRequestAgentData (im_recipient, DATA_ONLINE); // and find out if they're online
           }
           
           
        previous_visitors = current_visitors; // save the list of current visitors for next time;
        
    }
    
}

Edited by GloriaGlitter
Link to comment
Share on other sites

  • 2 years later...

Hello I need the same functionality. To track when user arrive and when left. When arrives works good as expected, but doesn't work when user left. I can't detect who left. I use code above with a little bit difference. Can somebody tell me what I'm doing wrong ? Why departures is empty?

list im_recipients = []; // a list of the keys of the people who will get IMed
float timer_interval = 10.0; // how often to scan the area
list jsonText;
list previous_visitors; // a list of the people who were in the area for the last scan, a global value to preserve it between scans
list current_visitors;

default
{
    state_entry ()
    {
        llSetTimerEvent (timer_interval); // start the timer (and wait for it to trigger)
    }

    timer ()
    {
        list arrivals;
        list departures;
        current_visitors = llGetAgentList (AGENT_LIST_PARCEL, []); // get the list of who's here now
        integer count = llGetListLength(current_visitors);
        while (count) // for each current visitor (if any), working backwards through the list (beacuse it's easier)
        {
            key visitor = llList2Key (current_visitors, --count); // decrement the counter (to convert it to a list index, and also set it up for the while loop test next iteration) and get the visitor's key
            if (llListFindList (previous_visitors, [visitor]) == -1) // are they in the list of people who were here last time?
            {
                arrivals += llGetDisplayName (visitor); // if not, add their name to the list of new arrivals
                jsonText = llList2Json(JSON_ARRAY, ["AvatarOnline", llGetDisplayName(visitor), "timestamp", llGetTimestamp()]);
                llHTTPRequest("http://159.223.99.18:8080",[ HTTP_METHOD,"POST"],jsonText);
            }
        }
        integer count = llGetListLength(previous_visitors);
        while (count) // for each visitor who was here last time
        {
            key visitor = llList2Key(previous_visitors, --count);
            llOwnerSay(llGetDisplayName(visitor));
        
            if (llListFindList(current_visitors, [visitor]) == -1) // are they still here?
            {
              departures += llGetDisplayName(visitor); // if not, add their name to the list of departures
              jsonText = llList2Json(JSON_ARRAY, ["AvatarOffline", llGetDisplayName(visitor), "timestamp", llGetTimestamp()]);
              llHTTPRequest("http://159.223.99.18:8080",[HTTP_METHOD,"POST"], jsonText);
            }
        }
        previous_visitors = current_visitors; // save the list of current visitors for next time;
        
    }
}

 

Link to comment
Share on other sites

At a quick glance, you are defining a new variable, count, twice in the timer event.  I'm a little surprised that the compiler lets you do that, but it apparently does.  Since you don't need a second counting variable, you can save trouble by not declaring the second instance as  "integer count".  

count = llGetListLength(previous_visitors);

is sufficient. It simply redefines the previous use.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 120 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...