Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Multiple Avatar touches

Robins Hermano
Registered User
Join date: 20 Oct 2006
Posts: 18
01-24-2009 11:17
I have a written a script to record Avatar names and key along with other relevant data I use in a class I teach. The script works fine and the data collected in SL is successfully sent to a PHP script that stores the data. The event that starts the process is a touch_start which generates a dialog box allowing the avatar to choose registration options. The problem I'm having is that when multiple avatars touch the object to begin the registration process their data (which they provide via chat channel) gets mixed up and so one piece of data from avatar1 is combined with information from avatar2 and so on. I know (well I think) I have to somehow control what I'm collecting using the number of touches from the touch_start event but am unsure how to proceed, any help will be greatly appreciated. Here are the relevant parts of the code:

touch_start(integer number)
{
AVKey = llDetectedKey(0);
AVName = llDetectedName(0);
llDialog(AVKey,"\nPlease choose an option:\n",["Add", "Change", "List"],channel);
}

listen(integer channel, string name, key id, string message)
{
if (message == "List";) {
requestid = llHTTPRequest("http://www.mydebitcredit.com/php/list_registered_students.php",
[HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"],"AVName=" + AVName + "&Key=" + (string)AVKey );
}
else if (message == "Change";) {
llInstantMessage(AVKey, "What do you want to change your NID, Twitter account or email address? \nType either Nid, Twitter or Email then a space and then type your new NID, Twitter Account or Email Address. \nRemember to start your chat with /2021 and a space, so for example to change your e-mail type the following:\n/2021 Email [email]shornik@bus.ucf.edu[/email]";);
llListen(2021,"", AVKey, "";);

}
else if (message == "Add";) {
llInstantMessage(AVKey, "Please enter the following information by typing it in the chat window.\n Begin the chat with /2021 followed by a space, your NID,Twitter Account, and Email. \n Seperate each of the following with a comma: \n Your NID, Twitter account name (if you don't have one leave a blank space), and your email address. \n Please don't leave any spaces between them so for example what you type might look like this: \n /2021 sh123456,acg2021,shornik@bus.ucf.edu";);
llListen(2021,"", AVKey, "";);
}
else if (llGetSubString(message,0,6) == "Twitter";) {
ChangeData = llParseString2List(message,[" "],[""]);
twitter = llList2String(ChangeData,1);
twitter = llStringTrim(twitter,STRING_TRIM);
update = llGetSubString(message,0,6);
requestid = llHTTPRequest("http://www.mydebitcredit.com/php/update_registered_students.php",
[HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"],"AVName=" + AVName + "&Key=" + (string)AVKey + "&TwitName=" + twitter + "&changed=" + update);
}
else if (llGetSubString(message,0,2) == "Nid";) {
llSay(0, "Im in the Nid Change";);
ChangeData = llParseString2List(message,[" "],[""]);
NID = llList2String(ChangeData,1);
NID = llStringTrim(NID,STRING_TRIM);
update = llGetSubString(message,0,2);
requestid = llHTTPRequest("http://www.mydebitcredit.com/php/update_registered_students.php",
[HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"],"AVName=" + AVName + "&Key=" + (string)AVKey + "&Nid=" + NID + "&changed=" + update);
}
else if (llGetSubString(message,0,4) == "Email";) {
ChangeData = llParseString2List(message,[" "],[""]);
Email = llList2String(ChangeData,1);
Email = llStringTrim(Email,STRING_TRIM);
update = llGetSubString(message,0,4);
requestid = llHTTPRequest("http://www.mydebitcredit.com/php/update_registered_students.php",
[HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"],"AVName=" + AVName + "&Key=" + (string)AVKey + "&Email=" + Email + "&changed=" + update);
}
else {
StudentData = llParseStringKeepNulls(message,[","],[""]);
NID = llList2String(StudentData,0);
NID = llStringTrim(NID,STRING_TRIM);
twitter = llList2String(StudentData,1);
twitter = llStringTrim(twitter,STRING_TRIM);
Email = llList2String(StudentData,2);
Email = llStringTrim(Email,STRING_TRIM);
llInstantMessage(AVKey, "NID" + NID + "Twitter: " + twitter + "Email: " + Email);
requestid = llHTTPRequest("http://www.mydebitcredit.com/php/register_students.php",
[HTTP_METHOD, "POST",HTTP_MIMETYPE, "application/x-www-form-urlencoded"],
"Nid=" + NID + "&AVName=" + AVName + "&Key=" + (string)AVKey + "&TwitName=" + twitter + "&Email=" + Email);
}
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
01-24-2009 11:46
Thinking out loud ..... Would it work to put the listen handler in the touch_start event and then put a loop around all the statements in that event, something like this?

CODE

touch_start(integer number)
{
integer i;
for(i=0;i>=number;++i)
{
AVKey = llDetectedKey(i);
AVName = llDetectedName(i);
llDialog(AVKey,"\nPlease choose an option:\n",["Add", "Change", "List"],channel);
llListen(channel, "", AVKey, "");
}
}


Will this work, or will each successive listen handler overwrite the previous one?
Papalopulus Kobolowski
working mind
Join date: 11 Aug 2006
Posts: 326
01-24-2009 13:43
just lock the touch and use another state where the second avi is compared to the first avi key or name until the first avi make the registration or cancel the registration in this way only one avi can register at time
Kayaker Magic
low carbonated footprint
Join date: 11 Sep 2008
Posts: 109
12-19-2009 01:41
I've always been good and written my code to look at all the touches send to touch_start, even when I could have gotten away with just looking at the zeroth one. Now for the first time, I have a use for all those touches, and I'm sending them to a bunch of linked prims as messages. There's only one prim in the build with the code below. So with two side-by-side computers I mash down on the mousekeys at the same time, and I never get two at once! Both avatars raise their arm, but only one of the messages gets through. I put diagnostic printouts in touch_start and it says there is only one touch (num==1 in the code below). The other avatar is still standing there with his left arm up. Why am I not getting all the touches?

CODE

default
{
touch_start(integer num)
{
while (--num>=0)
{
key av=llDetectedKey(num);
vector enpos=llDetectedTouchST(num); //they touch and end position
//send to all the seats that all the avatars are sitting on
llMessageLinked(LINK_ALL_CHILDREN,0,"jump|"+(string)enpos,av);
}
}
} //default
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-19-2009 13:19
CODE

touch_start( integer num ){
// llOwnerSay( (string)num );
do{
--num
llMessageLinked( LINK_ALL_CHILDREN, 0, "jump|" + (string) llDetectedTouchST( num ), llDetectedKey( num ) );
}while (num);
}

looks fine should work, I tweaked it so you didn't need variables every pass and saved 1 test with a do (since there will always be one if it triggers)

two things to remember... with a set up like this the touches are processed last to first and if the touch event is entered before the second av touches, it'll be queued as a separate event. which means unless it was already running some other they won't be queued together unless they were within .2sec of each other.
uncommenting the ownersay should demonstrate this effect.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
DoteDote Edison
Thinks Too Much
Join date: 6 Jun 2004
Posts: 790
12-19-2009 17:48
The only problem I see with your initial script is that you store the toucher's name and key as global variables. Then you use those same globals in the listen() event. However, before a user chooses an option from the dialog, another user clicks your object and resets the name/key globals. There's a very simple solution to that:

The listen event returns the name and key of the avatar who responds via dialog. Therefore, no reason to store global names/keys. When the person clicks, call the llDialog() and process the name/key received within the listen() event.

As for using a loop in the touch_start() event, I've never understood that... the loop method is useful within a touch() event, where multiple avatars can touch at once. But, my understanding is there can only ever be one touch_start() at a time... When two try to touch at the exact same time, one is going to "win-out" by a fraction of a nano-second. The event will then re-trigger for the "second-place" toucher. So, the loop is pointless... but I've never tested to see if "num" ever increases beyond zero in a touch_start. I could be wrong.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-19-2009 18:01
psst, necromancy in effect, OP's problem is now irrelevant.

and the loop in touch_start really doesnt protect against simultaneous touches so much as it allows you to grab all queued touchers (if for instance you happen to in the middle of executing a different code segment when those events are triggered)

demo:
CODE

default{
state_entry(){
integer vIntCnt = 10;
do{
llSleep( 2.0 );
llSay( 0, (string)vIntCnt );
}while (--vIntCnt);
llSay( 0, "ready" );
}

touch_start( inter vIntTouchers ){
llSay( 0, (string)vIntTouchers + " people touched and were queued." );
do{
llSay( 0, llDetectedName( --vIntTouchers ) );
}while (vIntTouchers);
}
}


have several people touch it while it's counting down.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
12-19-2009 19:20
I haven't thought about his since I posted a reply to the OP back in January, but would it be possible to try a variation of what I suggested then? Something like ....

CODE

integer CHAN = -1234; //global declaration
integer AllAvs; //global declaration

touch_start(integer number)
{
AllAvs = number;
integer i;
for(i=0;i>=number;++i)
{
llDialog(llDetectedKey(i),"\nPlease choose an option:\n",["Add", "Change", "List"],CHAN+i);
llListen(CHAN+i, "", llDetectedKey(i), "";
}
}

listen (integer channel,string name, key id, string msg)
{
while (--(AllAvs+2))
{
if(channel == CHAN+AllAvs)
{
// Do dialog stuff
llListenRemove(AllAvs);
}
}
}


I can't get in world to test this, and my head aches trying to figure out whether the queued messages from multiple touching avs will be heard properly each time the listen event is triggered. I'm sure that I'm not expressing things quite correctly, but does this approach make sense?
_____________________
It's hard to tell gender from names around here but if you care, Rolig = she. And I exist only in SL, so don't ask.... ;)

Look for my work in XStreetSL at
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-19-2009 23:24
since we're looking at the old problem (how to separate av responses) I've looked at a few ways, but the most effective seems to be to just capture their key as they respond and tie an data collection to that if needed. (loads easier than opening a unique listen)

if you are using a dialog, even better as you can encode other information in the buttons to let you know where you are in a multi-step sequence with that particular av or use different channels for different steps.

then the question becomes, when to turn off the listen(s)... which can be done with a timeout timer.

OP probably shouldv'e tied the avatar ID and the query ID together, so that any confirmation messages from the http calls went back to the intended source. (although they were trying to use the av key variable from the touch event in the listen, so no wonder it acted weirdly)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Kayaker Magic
low carbonated footprint
Join date: 11 Sep 2008
Posts: 109
12-20-2009 00:35
Well this is frustrating. I thought it was polite to tack a related question onto an old posting. But all I've done is get everyone interested in re-solving the OP and no-one is addressing my addition to it! Should I go start a new thread?
To restate my question: Has anyone every seen the integer parameter of touch_start with a value greater than one? I created a situation where it SHOULD and IT DID NOT. Yes, sometimes my fingers on the two computers came down on both sides of a 0.2 second cycle. In that case I got two calls from touch_start, each with a value of 1. But when I managed to mash them both down in the same 0.2 interval, touch_start was called once with a parameter of 1, and one of the touches was lost forever. I know that it was lost because both avatars raised their hands, but the one with the lost touch never lowered it. And a second call to touch_start never happened.
I've noticed that touch_start had this capability, I've seen recommendations that one should write ones code to handle it, BUT HAS ANYONE EVER ACTUALLY SEEN IT HAPPEN? And is there something that I am doing (which I can fix) that will allow it to happen for me? I actually have an application where I want to be able to handle multiple simultaneous clicks from different avatars.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-20-2009 00:55
look up at the last example code I posted... that demonstrates proof of concept for multiple av's touches being queued. (a single av will only be queued once per event, regardless of the number of touches it initiates, which can be demonstrated at the same time)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Kayaker Magic
low carbonated footprint
Join date: 11 Sep 2008
Posts: 109
12-20-2009 22:34
From: Void Singer
look up at the last example code I posted... that demonstrates proof of concept for multiple av's touches being queued.

Your statement is ambiguous: Do you mean "This code worked and printed out numbers greater than 1" or do you mean "this untested code shows how you are supposed to get numbers greater than 1"
I stuck your code into an object and ran it.

Here is an example output where the two avatars touched more than 0.2 seconds apart:
[21:57] Object: Kayaker Magic
[21:57] Object: 1 people touched and were queued.
[21:57] Object: Crashtest Crystal
[21:57] Object: 1 people touched and were queued.
[Curiously, the name of the touchee often appeared before the 'first' line of output. Are llSay calls not guaranteed to output in order???]

Here is an example output where the two avatars touched within a 0.2 cycle:
[21:58] Object: 1 people touched and were queued.
[21:58] Object: Crashtest Crystal

Both avatars raised their arms, but touch_start only ever reported one. Only one name was ever printed, and there was never a second call to touch_start. One of the touches was lost. Sometimes it was me, sometimes it was Crashtest who won the race. The test was done with two Mac computers side by side, Emerald running on both of them. One person (me) clicked both mouse keys at once to try and start them at the same time. I repeated the experiment many times, and never saw a number greater than 1 reported by touch_start.

I tried another experiment:
I modified the program to print out one too many names, to see if all the touchers were there with just a wrong count. Alas, this did not work. The second toucher (index 1) was always the null key. My question still stands, has anyone ever seen touch_start return a number greater than 1?

I tried ONE MORE EXPERIMENT:
I modified the program to use touch_end instead of touch_ start AND I SAW A COUNT OF 2! In this program I never lost one of the touches! It is harder to synchronize the release of two mouse buttons, so there were many cases where touch_end was called twice with one avatar each, but it was possible to see two avatars in one touch_end call.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-21-2009 00:41
viewer chat may display out of order... it's in order on the server though, so non-issue for our purposes...

I did see some of that two separate single queues weirdness on the first touch event in a state... I'm not sure if it's because of some misbehavior, or because state_entry gets some sort of special treatment. it was consistent for mono and lso...

this demo DOES work as conceived
CODE

default{
touch_start( integer vIntTouchers ){
llSay( 0, (string)vIntTouchers + " people touched and were queued." );
integer vIntCnt = 10;
do{
llSleep( 2.0 );
llSay( 0, (string)vIntCnt );
}while (--vIntCnt);
}
}


as far as I can tell, only the first click event after entry into a state behaves oddly, after that it seems to queue normally, which means multiple possible touchers per event fired.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Kayaker Magic
low carbonated footprint
Join date: 11 Sep 2008
Posts: 109
12-21-2009 21:39
Curiouser and curiouser. Sure enough, Void's most recent test DOES get a value of 2 to touch_start. But only because the sleep is inside the touch_start event. My real scripts are normally silent: between events, not sleeping inside an event, and certainly not sleeping in touch start. I moved the sleep out of touch_start and into timer in the code below, and had the following results:

If two avatars clicked at the same time during the quiet 5 seconds between timer events, one was lost and only one touch was queued.

If two avatars clicked at the same time during an llSleep in timer, one touch was lost and only one touch was queued.

If two avatars clicked a second or more apart while timer was looping, then when timer finished, touch_start was called twice, once for each avatar with a parameter of 1. No touches were lost in the making of this scenario.

I still don't think this is working right. How do you submit a bug report to the Lindens? When I was a noob, I once tried sending a bug report as a ticket to the main SL help page. A bot answered telling me that since I'm not a premium member, no human ever saw my helpful report, instead it was digitally spat upon, stomped on, folded, spindled, mutilated and tossed into /dev/null. I Notice that they warn you now on the support page that this will happen, instead of dissing you after you wasted your time reporting a bug to them.

CODE

default
{
state_entry()
{
llSetTimerEvent(15);
}
touch_start( integer vIntTouchers )
{
llSay( 0, (string)vIntTouchers + " people touched and were queued." );
}
timer()
{
integer vIntCnt = 10;
do
{
llSleep( 1.0 );
llSay( 0, (string)vIntCnt );
}while (--vIntCnt);
}
}
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-21-2009 22:36
the sleep during the touch event wasn't meant to simulate idle time between normal event calls, but to simulat the script doing something already which requires the event to be queued.

if the script is idle, it may very well take less than .2 seconds before the event fires, in which case it'd be almost impossible to catch "simultaneous" clicks.

I do wonder about one thing though... you seem to be losing a lot of clicks... you may want to try a faster or less loaded sim, because I'm no seeing that.

jira.secondlife.com is where you would report the discrepancy, but as far as necessity goes, if multiple agents are only queued while the touch event is running, it still shows they can be, and therefore need to be handled.

(for fun try a touch sequenece of A-B-A with the original script PoC... you'll get a queue of A and then one with B and A)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
shootjutsu Absent
Registered User
Join date: 28 Oct 2009
Posts: 15
12-21-2009 22:53
test