Alrighty then, here is my first post involving some original coding technique by yours truly. As some of you might have noticed, there is only one type of information that can be directly handed down from a parent prim to its rezzed 'children' (I use the term loosely in this article, as a child prim is typically part of the same linkset as the parent prim), and that is the integer designated as a 'starting parameter'. While start params have their uses, the fact that only integers can be used is quite limiting in application; ideally one would want the variable type to be a string or perhaps another variable type, depending on the situation (a string would be best though, seeing as it can be typecast to any other variable type). Anyone who has run into this problem has likely tried a number of workarounds, most involve bouncing chat messages back and forth, some use HTTP requests (if one has access to PHP and databases), some use more unconventional methods. While a reliable technique is not the most difficult thing to churn out, many people employ rather inefficient or slow ways of transferring this information; the goal of this article is to provide you with the (in my opinion, and I have yet to be proven wrong) fastest and simplest method of transferring a string of info from a rezzer script to a rezzed one.
So, when I first started requiring a transfer such as the one I've been talking about, my first method worked to great effect, but it was -very- clunky. It would get the info across, sure, but doing things in rapid succession was out of the question. At the time it seemed the only way to do it, so I stuck with it. It involved the arduous process of opening a listen event in the rezzer script, rezzing the object, then having the rezzed object open up it's own listen event and send a ready message (you could theoretically just throw the message blindly after rezzing but, due to lag, the prim might not be listening yet...and adding a llSleep() delay just slows things up further when it might not always be necessary) to the original script...which would then reply with the desired information and listeners on both ends would close. This works well enough, and it seems to be the popular method among many scripters today...however, it is a lot of unnecessary work and can get extremely slow between chat messages in laggy sims. Next, I tried to slightly better effect a method that, after rezzing, would spout off the info on a very short timer event until it received a confirmation from the script that the content went through, similar but still too slow for some really heavy-duty work. Several months later I had the (at the time brilliant, I thought) idea to nix the listeners altogether and use HTTP requests, combined with some handy PHP and a mySQL database. The basic procedure involved posting the transferring info to said database, along with an integer that was designated as a 'reference ID' that could be used to retrieve the info at a later date. This reference ID was then passed along to the rezzed prim as the starting parameter, and then utilized accordingly to snatch the info up from the database. This actually worked surprisingly well, and as fast as the script could handle it; the only downside was that there was a lot of superfluous coding involved...there had to be a setup for converting the info to a plausible HTTP request, as well as an entire http_response event that was only used once and then laid dormant. I used this for about a year's time until one fateful day when my web hosting up and disappeared (long story)...leaving me without one of the most important functions (among many, many others) that my scripts relied upon to operate. Needless to say, I had to come up with another method to run said scripts on, because I sure wasn't looking forward to going back to the clunky original procedure. Thus, the following setup was born...and although I'm probably not the only one to utilize such methodology, I sure don't want you guys to have to go through the same long process of finding out how to pull it off that I did. It is both fast AND uses a minimal amount of coding, and doesn't rely on an outside source such as databases and the like. So here it is...Arkane's String-Transfer Extraordinaire. Let's take a look:
First, we have the object_rez event in the rezzer script
object_rez(key id)
{
while(llList2String(llGetObjectDetails(id,[OBJECT_DESC]),0) != "listening") //check the description field of the rezzed prim
;//do nothing until the prim is ready
integer myChan = -1 * (integer)("0x"+llGetSubString((string)id,-5,-1));//generate a random channel based on the rezzed object's UUID
llRegionSay(myChan,myString);//spout it off
}
Basically, what is going on here is this: once the object is rezzed, the rezzing script checks VERY rapidly (as fast as it can process, really) the description field of the rezzed prim, waiting for the moment it says 'listening' (to indicate the listen event is open, duh). Once this is accomplished, an channel integer is created that is based off of the UUID of the rezzed prim (the rezzed prim will have already arrived at this same integer and opened a listener on that channel) to regionsay the info on...and then subsequently do so. That's all the work that the rezzer script has on its plate, its job is now complete. No listeners, no timers, no nothin'. The above code can be compressed to just two lines (I expanded it for purposes of the example), here's what it looks like:
object_rez(key id)
{
while(llList2String(llGetObjectDetails(id,[OBJECT_DESC]),0) != "listening");
llRegionSay(( -1 * (integer)("0x"+llGetSubString((string)id,-5,-1)) ) + 135,myString);
}
Pretty neat, huh? Quick, easy, and to the point. Now let's take a look at the code the rezzed prim uses:
on_rez(integer start_param)
{
if(start_param)
{
myListen = llListen( -1 * (integer)("0x"+llGetSubString((string)llGetKey(),-5,-1)),"","","");//open up the listener, based on the prim's UUID
llSetObjectDesc("listening");//let the rezzer script know it's ready to receive the info
}
}
The above coding basically does the following: if it has a start parameter set (meaning it came out of an object and not inventory, make sure to accommodate for this in your original llRezObject() or llRezAtRoot() call), then open up a listener using the same logic as the rezzer script. After this has been accomplished, simply change the object's description field to 'listening' to let the rezzer know it has done so. Now let's go to the listen event used to handle the info:
listen(integer chan, string name, key id, string msg)
{
llListenRemove(myListen);//always be responsible and take out unused listeners
myInfo = msg;//store the info in a variable
}
Isn't that easy? We remove the now useless listener and capture the info that came through it in a variable, to be used in whatever manner might be required. The whole process is almost instantaneous, and is pretty much infallible, assuming that the script is able to function (rezzing and scripts must be turned on for the parcel, of course)...and you don't use any code that might deliberately tamper with it. If you need the description field for other purposes, consider instead changing the color, size, or related parameter of the prim to something that would indicate that the listener is now ready to receive information. I'm positive you can find some way to do this without harming your other processes that you might be utilizing, there are loads. And that is that, hopefully this article helps you find a better way to run your data-transfers. And please, if you have and questions, comments, complaints, or even (especially) a better way of achieving this effect, feel free to leave a comment or message me in-world.
~sugArkane Flux