Passing a key via on_rez (concept)
|
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
|
12-16-2005 14:26
You should also mention that the guarantee of success for this scheme is 99.99999%, but not 100%, because there is always the mathematical possibility that the object will find two candidate keys in its sensor scan that both map to the provided hash value  Actually, since an integer is 32 bits, you have a 1 : 2^32 chance that a second key will fall into the same hash bucket. So that's a 0.000000023283064365386962890625% chance of failure (if you trust the Windows XP calculator  )
|
Yumi Murakami
DoIt!AttachTheEarOfACat!
Join date: 27 Sep 2005
Posts: 6,860
|
12-17-2005 06:17
From: Ghordon Farina ^.^ is this online? I'd love to read.
http://www.geocities.com/patchnpuki/other/compression.htm
|
Norman Desmoulins
Grand Poohba
Join date: 10 Nov 2005
Posts: 194
|
12-17-2005 07:14
From: Ghordon Farina By the way, I wrote the scripts for the transmission of a hash from the parent to the child prim so that the child detects the user requested. I'll post it here later, once I comment it (for the new users who may not understand anything yet).
People just want to get stuff done most times... there are a very few who care about the real implementation details... and the ones that do can tell without comments. If you have something that works, just post it, without the comments.
|
Ghordon Farina
Script Poet
Join date: 1 Nov 2005
Posts: 126
|
12-17-2005 11:38
From: Norman Desmoulins People just want to get stuff done most times... there are a very few who care about the real implementation details... and the ones that do can tell without comments. If you have something that works, just post it, without the comments. This is true. However, occasionally you'll find the aspiring scripter who values those comments to read and learn from. This is one of those cases where I work not only for the masses, but for the little guys too. Not only that, but for you to modify the code to do what you want it to do rather than just what I had it do, you'll need to know how it works. Hence, comments. (Waves his ego flag valiantly once more.) (Puts the flag away and says "just kidding."  (Posts his code and gets out of the way.) Here is the code for the parent prim: // Passing a key via on_rez(..) // using a hash rather than sending a whole key // // By Ghordon Farina // (enjoy!)
integer listener; // the value we'll use to open/close listeners key owner; // the owner of the script string who; // the name of the person we're targeting
integer makehash(key id){ // this function is used to create the hash that is passed to the child prim // 1. Take the first 4 letters from their key // 2. Convert them to an integer (via llBase64ToInteger) // 3. Return the integer integer num = llBase64ToInteger(llGetSubString((string)id,0,3)); return num; }
default { on_rez(integer spam){ llResetScript(); // so that we start with a clean slate, no recycled variable values } state_entry(){ owner = llGetOwner(); listener = llListen(0,"",owner,""); // only listen to what the owner has to say (reduces lag) } listen(integer channel,string name,key id,string msg){ llListenRemove(listener); // end the listener name = llToLower(msg); // convert to lowercase so that names don't have to be case-sensitive list names = llParseString2List(name,[" "],[]); // convert the command given to a list if(llList2String(names,0) == "find"){ // check to see if we've been ordered to "find" someone who = llList2String(names,1) + " " + llList2String(names,2); // get the name of the target llSensor("",NULL_KEY,AGENT,96,TWO_PI); // start a sensor to find them } listener = llListen(0,"",owner,""); // start a new listener // You may ask "Why stop and restart the listener every time it hears something?" // The reason is this: when you start a listener and have it listen forever, after // a certain point, it overflows due to having recorded too many listens. // Even though this might be unrealistic for a limited script, building the listener // reset into the script will prevent this from ever happening. // (This is based on my personal experience with llListen().) } sensor(integer spam){ integer x; // a counter key found = NULL_KEY; // a key (which we'll pass to the hash) for(x=0;x<spam;x++){ // for ever person in the room: if(llToLower(llDetectedName(x)) == who){ // check to see if their name matches the one we're looking for llOwnerSay("Found!"); // if so, tell the owner... found = llDetectedKey(x); // get their key... integer num = makehash(found); // convert it to an integer... llOwnerSay((string)num); // tell the owner that number... llRezObject("test",llGetPos() + <0,0,1>,<0,0,0>,ZERO_ROTATION,num); // rez the child prim, using that number as the passed argument // NOTE: The name of the child prim rezzed is "test" so make sure you either // 1. Change that to the name of your child prim // or 2. Change the name of your child prim to "test" } } if(found == NULL_KEY){ // if nobody was found, tell the owner! llOwnerSay("Agent not found."); } } }
And here is the code for the child prim: // Passing a key via on_rez(..) // using a hash rather than sending a whole key // // By Ghordon Farina // (enjoy!)
integer hash; // the integer that we'll use to find the key of the target key id = NULL_KEY; // the key of the target
integer makehash(key id){ // this function is used to create a hash to test against the passed hash // 1. Take the first 4 letters from the key // 2. Convert them to an integer (via llBase64ToInteger) // 3. Return the integer integer num = llBase64ToInteger(llGetSubString((string)id,0,3)); return num; }
default { on_rez(integer spam){ hash = spam; // set hash to the passed integer (so that we make it a global) llOwnerSay("Searching for key corresponding to "+(string)spam); // tell the owner llSensor("",NULL_KEY,AGENT,96,TWO_PI); // start a sensor to find the target } sensor(integer numfound){ integer x; // a counter for(x=0;x<numfound && id == NULL_KEY;x++){ // for each detected agent if(makehash(llDetectedKey(x)) == hash){ // hash their key and see if it matches the passed hash llSay(0,"Found! Name: "+llDetectedName(x)); // if so, tell us! id = llDetectedKey(x); // and save their key } } if(id == NULL_KEY){llSay(0,"Could not find agent.");} // if we didn't find them, tell us! llDie(); // die (only because we have no use for you anymore) - how melodramatic! } }
|
Haravikk Mistral
Registered User
Join date: 8 Oct 2005
Posts: 2,482
|
12-17-2005 14:48
Looks like a ton of discussion has gone into this, but erm, is it not just easier overall to give the on_rez event a listen channel and whisper the key immediately?
|
Ghordon Farina
Script Poet
Join date: 1 Nov 2005
Posts: 126
|
12-17-2005 16:38
Yes, it would be faster, but it would also (in some cases) be a worse choice, reliability/memory/lag wise.
Imagine you're building an automatic gun, which throws out 50 bullets per second (not unreasonable). You want the gun to target a single avatar, then tell each bullet as it's sent out to only attack that avie.
Here is a comparison between your idea (pass via llSay) and our idea (pass via on_rez):
a. llSay would require that each bullet have a listener in range of the parent object (the gun) for it to llListen to get the key. Assuming that you're moving and the bullets are moving, you'll have to pray that the bullets will still be in range of your avie so that they can hear. Not to mention you'd have to llSay the key every single time you rez a bullet (or close to it).
b. Passing the hash via on_rez removes the worry about the bullet moving too far too fast, and it doesn't require a llSay every time it's rezzed, nor does it require a listener. (50 llListens per second can lag a sim pretty fast.) The bullet is going to have to llSense the agents anyways, so reducing the llListens will lag the sim less. The bullets themselves will worry about finding the avatar.
As you can see, it would be FAR more reliable and lag-less if you pass on_rez rather than via llSay.
Of course, there are some cases that might be more practical with llSay() but I can't think of any right now (nor have i tried).
Yep.
|
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
|
12-17-2005 19:21
From: Yumi Murakami I think at this stage we have to move to asking, how ARE keys generated? There's actually a formal spec for what a UUID contains! It';s all documented! It's not random, but for this purpose it's effectively random.
|
Ghordon Farina
Script Poet
Join date: 1 Nov 2005
Posts: 126
|
12-17-2005 21:59
Is there a link where we can see this documentation? So that we might understand how they're made? I think it would be a fun read...
(I'm such a geek.)
|
Haravikk Mistral
Registered User
Join date: 8 Oct 2005
Posts: 2,482
|
12-18-2005 07:39
From: Ghordon Farina As you can see, it would be FAR more reliable and lag-less if you pass on_rez rather than via llSay.. Hmm, IMO it wouldn't worth it to create such a fast-firing weapon in the first place  For starters, it would hardly be lagless, as some kind of processing (by the sound of it, quite a bit) will be needed to squash a key into an integer, or fetch it by some other means. There comes a point where compressing data rather than sending it raw becomes the worse option, as it can certainly end up being far from lagless. For such a weapon, I think a far more elegant solution would be simply to use particle effects for the bullets, and have a much less frequent, invisible 'bullet' shoot out to cause the actual damage.
|
Ghordon Farina
Script Poet
Join date: 1 Nov 2005
Posts: 126
|
12-18-2005 10:30
From: Haravikk Mistral Hmm, IMO it wouldn't worth it to create such a fast-firing weapon in the first place  For starters, it would hardly be lagless, as some kind of processing (by the sound of it, quite a bit) will be needed to squash a key into an integer, or fetch it by some other means. There comes a point where compressing data rather than sending it raw becomes the worse option, as it can certainly end up being far from lagless. For such a weapon, I think a far more elegant solution would be simply to use particle effects for the bullets, and have a much less frequent, invisible 'bullet' shoot out to cause the actual damage. Processing to squash: llBase64ToInteger() and llGetSubString(). Very quick, one-time things. And if you write properly, it only has to do that ONCE, before spawning all the bullets. MUCH less laggy (and much less processor-abusing) than a bunch of llListen() llSay() functions. The hash function does NOT compress the data. Instead, it takes the data, cuts a piece off, and sends that instead of the whole key. Nothing extravagant. If you read the scripts I posted, you'll see that they are much less laggy than a setup of llListens for every bullet. However, I do agree with your idea of the particles and the invisible bullets. Though particles are laggy on the client-side, they can be reduced, and the 10-per-second rather than 50-per-second invisible bullet would be much more manageable server-side. (When I said 50-per-second, I was saying it to make a point about how the relative functions would cause more/less lag on the sim. Since 5 bullets at a time in the sim wouldn't slow it down much at all, I had to blow things out of perportions to make a point.)
|