Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Multiple llRequestAgentData calls and only one dataserver response

Feline Slade
Hatstand 2.0™
Join date: 19 May 2007
Posts: 201
11-04-2007 08:06
I've been staring at this for hours and can't seem to get it handled. Perhaps one of the veterans here can help me.

This script uses link_message to receive a list of UUID keys from another script and converts it to a list. It then uses the message number to identify that it is the correct message and validates the data format/length. If the data passes that validation, it performs llRequestAgentData to get the online status of the agent.

The problem seems to be that although llRequestAgentData is being performed multiple times, the dataserver event handler is only returning one result.

Sample code follows. Any ideas are (very) welcome.


// Global Variables

key onlineStatusRequest;

string incomingText;
string incomingKeyID;
string avatarStatus;
string avatarStatuses = "";

integer avatarNumber = 1;
integer incomingNumber = 0;
integer incomingListLength = 0;

list incomingList;


default
{
on_rez(integer startParam)
{
}

//When this script receives a message
link_message(integer Sender, integer Number, string Text, key ID)
{
incomingText = Text;
incomingNumber = Number;
incomingKeyID = ID;
incomingList = llParseString2List(incomingText,["|"],[]);
incomingListLength = llGetListLength(llParseString2List(incomingText,["|"],[]));


// if string of avatar keys is received which is the proper length (eliminates partial lists)
if (incomingNumber == 40 && incomingKeyID == (string)incomingListLength )
{
integer x;
integer length = llGetListLength(incomingList);

for(x = 0; x < length; x++)
{
onlineStatusRequest = llRequestAgentData(llList2String(incomingList, x), DATA_ONLINE);
llOwnerSay("sent request for " + llList2String(incomingList, x) + " status";); // debug aid - confirms that a request was sent
}
}
}



dataserver(key queryid, string data)
{
if (queryid == onlineStatusRequest) // check to be sure this is the correct llRequestAgentData query
{
llOwnerSay("Online status returned a value of " + data); //debug aid - result of online status request
if (data == "1";) // online status is just 0 or 1
avatarStatuses = (avatarStatuses = "";) + avatarStatuses + "Online" + "|";
else
avatarStatuses = (avatarStatuses = "";) + avatarStatuses + "Offline" + "|";
}
}
}
Day Oh
Registered User
Join date: 3 Feb 2007
Posts: 1,257
11-04-2007 08:15
Hello howdy (:

From: someone
for(x = 0; x < length; x++)
{
onlineStatusRequest = llRequestAgentData(llList2String(incomingList, x), DATA_ONLINE);
llOwnerSay("sent request for " + llList2String(incomingList, x) + " status";); // debug aid - confirms that a request was sent
}


Sends 3 requests very quickly, and onlineStatusRequest contains the ID of the very last query. In your dataserver event handler you're probably throwing away the responses most of the time because they don't match that query ID, if not all of the time if they were to arrive in order.

The simplest advice I can offer is to only send one request, wait for the response, then have your dataserver event handler make the next request, one at a time.

Or, you could keep a list of ID's for the queries you're waiting to receive. I'm not sure the responses are guaranteed to arrive in order.
_____________________
Feline Slade
Hatstand 2.0™
Join date: 19 May 2007
Posts: 201
11-04-2007 09:15
Thanks for your response, especially regarding the order of the responses. Ideally, I would wait for a response to each request, but all attempts I made at that failed, so I had resorted to this structure. Any suggestions about how to go about that?
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
11-04-2007 11:00
From: Day Oh
The simplest advice I can offer is to only send one request, wait for the response, then have your dataserver event handler make the next request, one at a time.
Is correct. You cannot predictably use a loop to process Events. You have to use the events themselves...

dataserver(key queryid, string data)
{
if (queryid == onlineStatusRequest) // check to be sure this is the correct llRequestAgentData query
{
llOwnerSay("Online status returned a value of " + data); //debug aid - result of online status request
if (data == "1";) // online status is just 0 or 1
avatarStatuses = (avatarStatuses = "";) + avatarStatuses + "Online" + "|";
else
avatarStatuses = (avatarStatuses = "";) + avatarStatuses + "Offline" + "|";

if (x < llGetListLength(incomingList) - 1)
{
x++;
onlineStatusRequest = llRequestAgentData(llList2String(incomingList, x), DATA_ONLINE);
}

}
}
Day Oh
Registered User
Join date: 3 Feb 2007
Posts: 1,257
11-04-2007 11:16
From: someone
for(x = 0; x < length; x++)
{
onlineStatusRequest = llRequestAgentData(llList2String(incomingList, x), DATA_ONLINE);
llOwnerSay("sent request for " + llList2String(incomingList, x) + " status";); // debug aid - confirms that a request was sent
}


Remove the loop so you just have
From: someone
onlineStatusRequest = llRequestAgentData(llList2String(incomingList, 0), DATA_ONLINE);
llOwnerSay("sent request for " + llList2String(incomingList, 0) + " status";); // debug aid - confirms that a request was sent


Then change your dataserver event handler to something like:

From: someone
dataserver(key queryid, string data)
{
if (queryid == onlineStatusRequest) // check to be sure this is the correct llRequestAgentData query
{
llOwnerSay("Online status returned a value of " + data); //debug aid - result of online status request
if (data == "1";) // online status is just 0 or 1
avatarStatuses = (avatarStatuses = "";) + avatarStatuses + "Online" + "|";
else
avatarStatuses = (avatarStatuses = "";) + avatarStatuses + "Offline" + "|";

// this is the bit I added
incomingList = llDeleteSubList(incomingList, 0, 0);
if(llGetListLength(incomingList))
{
onlineStatusRequest = llRequestAgentData(llList2String(incomingList, 0), DATA_ONLINE);
llOwnerSay("sent request for " + llList2String(incomingList, 0) + " status";); // debug aid - confirms that a request was sent
}
}
}


Hope that works o.o

Edit: Pale Spectre's solution avoids the silly list-work (:
_____________________
Feline Slade
Hatstand 2.0™
Join date: 19 May 2007
Posts: 201
11-05-2007 07:16
Thank you both very much for your help. Both approaches work very well, I see.

One question for you, Day Oh, because I don't like using code without understanding it...

From: Day Oh


// this is the bit I added
incomingList = llDeleteSubList(incomingList, 0, 0);
if(llGetListLength(incomingList))
{
onlineStatusRequest = llRequestAgentData(llList2String(incomingList, 0), DATA_ONLINE);
llOwnerSay("sent request for " + llList2String(incomingList, 0) + " status";); // debug aid - confirms that a request was sent
}

I'm confused by "if(llGetListLength(incomingList))". There doesn't appear to be a conditional statement to evaluate with the If. My ignorance is probably showing, but that reads to me as if it were saying "If 5" without saying what should be equal to or less than or greater than five. Am I reading it entirely wrong?

Thanks again for all of the wonderful and prompt help!
Day Oh
Registered User
Join date: 3 Feb 2007
Posts: 1,257
11-05-2007 14:13
My bad... It means "not equal to zero" (:
_____________________
Meade Paravane
Hedgehog
Join date: 21 Nov 2006
Posts: 4,845
11-05-2007 14:21
Conditions - the stuff in "if (stuff)" - **always** come down to being either true or false. False always has the value of 0 and true is anything that not zero.

So when you see something like "if (llGetListLength(incomingList))" it's really just looking at the return value of llGetListLength. If it's zero, that's a false and the condition fails. If it's not zero, that's a true and the condition succeeds..
_____________________
Tired of shouting clubs and lucky chairs? Vote for llParcelSay!!!
- Go here: http://jira.secondlife.com/browse/SVC-1224
- If you see "if you were logged in.." on the left, click it and log in
- Click the "Vote for it" link on the left
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
11-05-2007 15:03
It's a holdover from C-like languages where it treats booleans as integer values. The problem is that the 0=FALSE, (anything other than 0)=TRUE paradigm doesn't always hold up in other languages and platforms. It is best coding practice (and it actually reads better) to put the full conditional in the statement, rather than shortcutting. In LSL, it actually does generate a bit more code, and slows down your script a tiny bit, but I think the tradeoff is worth it, especially if someone (or yourself) has to come in behind you later and maintain your code.

Not to mention that some functions return -1 for failure, not 0 (like llSubStringIndex and llListFindList, for example), so it is not a meaningful way of determining such in a universal sense.