OK to trigger this event in a loop?
|
|
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
|
12-12-2008 17:23
A quick question ... In one corner of a larger script, I want to look through a list of avatar keys to determine whether each of them is on line at the moment. Here's the code I've written to do it. ActiveKeys is declared as a global list elsewhere. state signoff { state_entry() { integer j; integer length = llGetListLength(ActiveKeys); for (j=0;j<= length; j++) { llRequestAgentData(llList2String(ActiveKeys, j),DATA_ONLINE); } state manage_remote; // Done checking all keys. Go back to what I was doing before. } dataserver(key queryid, string data) { if(data == (string)(-1)) { // do a bunch of stuff } } }
The question is ... will this work? I'm triggering a new dataserver event each time I go around the loop in state_entry. Is this legitimate? If not, what's the way around it?
|
|
icktoofay Kamachi
Registered User
Join date: 10 Nov 2007
Posts: 17
|
12-12-2008 17:54
It will work AFAIK, but you might not get the responses in order. Edit: Read Viktoria's post below.
|
|
Viktoria Dovgal
…
Join date: 29 Jul 2007
Posts: 3,593
|
12-12-2008 18:01
That doesn't really look right, you make the request and switch states without waiting for the dataserver events to trigger.
It's really in the dataserver event where you'll want to check if all the outstanding requests from ActiveKeys have been returned, and then go on to the next state. You may also want a timer in that state to give up or retry if the responses take too long or never arrive (I hear that SL breaks sometimes).
|
|
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
|
12-12-2008 20:33
OK, so you'd recommend adding a llSleep after the loop, then? Or as the last step in each loop iteration? I hadn't thought about that.
The thing I was concerned about was jumping from state_entry to the dataserver event multiple times. I'm still new enough to LSL that I wasn't sure whether that sort of iteration between events was allowable. From your response and icktoofay's, it sounds like that's not a problem, so long as I give the dataserver event enough time to do its job. Right?
|
|
Viktoria Dovgal
…
Join date: 29 Jul 2007
Posts: 3,593
|
12-12-2008 20:49
When you're in an event (that includes state_entry), other events queue up and aren't handled until you are done with that event. So, you aren't really jumping back and forth, there will be a series of dataserver events triggered after you get out of state_entry. Adding a sleep would only make you wait longer.
|
|
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
|
12-12-2008 20:57
Oh, I see. I misinterpreted the flow of things..... didn't realize that the server requests would all be queued until after iterations around the loop. OK, so now I have two other concerns. First, can I be confident that the "stuff" I'm doing in the dataserver event will be done on the right data elements? For example, one of the things I need to do is to remove an avatar key from the ActiveKeys list if I find that the person is now longer in SL. Right now, I have written ActiveKeys = llDeleteSubList(ActiveKeys, j, j);
assuming that I can use the current value of j, declared as a global integer and passed from the state_entry event. Is that going to work if all the requests to dataserver are queued? Will the right value of j be applied to each request? Second, I thought I could go back to my previous state (state manage_remote) after completing the loop in state_entry. From what you say, that's maybe not the smartest thing to do. But what is? EDIT: AH..... If I wait long enough and think, I can answer at least part of my own question. I need to pass j not as a global variable but as a new value of queryid every time I go around the loop, right? Then I will always have the right value of j to do the "stuff" in the dataserver event. And, I leave the state when all values of j ( == queryid) have been dealt with, at the tail end of the dataserver event. Will that work?
|
|
Shifting Dreamscape
Always questioning ...
Join date: 12 Dec 2007
Posts: 266
|
12-13-2008 02:37
As commented above ... if you do things as they stand the dataserver return events will queue up waiting for the looping and state_entry to be complete, and then since you change state .. they will never be checked. My suggestion on doing this would be: //Global Variables integer gNumAvs; integer gCurrent; key gRequest;
state signoff { state_entry() { gNumAvs = llGetListLength(ActiveKeys);
//Set our counter to start at the end of the list //This is so we can remove items and not lose our place gCurrent = gNumAvs - 1;
//First Request gRequest = llRequestAgentData(llList2String(ActiveKeys, gCurrent),DATA_ONLINE); }
dataserver(key queryid, string data) { //Make sure it is our call to the datasever if (queryid = gRequest) { //Now if not online remove from the list .. and what ever else if(data == (string)(-1)) { ActiveKeys = llDeleteSubList(ActiveKeys, gCurrent , gCurrent); //what ever other code ... } //Now go for the next (if we are not done that is) --gCurrent; if (gCurrent > -1) { gRequest = llRequestAgentData(llList2String(ActiveKeys, gCurrent),DATA_ONLINE); } else { //All done state manage_remote; } } }
|
|
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
|
12-13-2008 07:05
Thank you. This beats the solution I had in my head as I woke up this morning.  I appreciate your help and everyone's patience as I slowly get my head around LSL's logical structure.
|
|
Shifting Dreamscape
Always questioning ...
Join date: 12 Dec 2007
Posts: 266
|
12-13-2008 09:04
Quick review and I realize that gNumAvs is not needed, just take the list length straight into gCurrent.
|
|
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
|
12-13-2008 11:43
I saw that too. Thanks. 
|