SL Updating Scripts

May 6, 2008 · Filed Under Second Life · Comment 

When I started scripting in Second Life, I quickly realized that I would have many dozens of objects that used the same script. This script would need to be updated in all of those objects repeatedly, not something I was looking forward to doing manually. While it would be ideal if multiple objects could reference the same script from a single location, that option is not available.

The next best option was to push the updated script from a central script server object to the client objects. A single script could handle serving the script using llRemoteLoadScriptPin(). This function pushes the specified script to an object with a specified key. If all of the objects that needed the script had the same name, then the central script could query those objects by name and create a list of their keys.

Not so fast. There is no function to return a list of object keys based on name or any other criteria aside from linkage. Due to the distances involved, linking was not an option. I certainly didn’t want to maintain a list of keys for the objects manually. And of course, the client object getting the script would need to have a matching pin number set for llRemoteLoadScriptPin() to work. Both of these issues meant that a client script was also required.

It’s easy enough to set the pin in the client script using llSetRemoteAccessPin(). However, how would the server script get the key of the client object? The client script needs to provide it. Not unlike an HTTP or FTP request, the client would need to request the script via chat and the server object, listening for the request, could provide the requested script back to the requesting object.

This created another issue: How is the client request initiated for each of dozens of objects? I added a listener to the client script that would listen for a specific chat command from my avatar on a private channel. This way, I could update objects within 20 meters via chat or objects up to 100 meters away via shout. This system has worked fairly well and only requires about 3 shouts to update the client scripts scattered across an entire region.

I also considered creating a single point of activation at the server. This could be done by adding another listener to the server which would broadcast an update request region-wide, prompting all of the clients in the region to request an update.

  1. Avatar to Server: hey server, broadcast update request to region
  2. Server to Region: if you can hear me, it’s time to update
  3. Client to Server: hey server, please send me this script
  4. Server to Client: sends script

I didn’t have the need to implement this by the end of this project, but may do so right at the beginning of my next SL project.

I have also added code to each script that queries the object name and prevents of the script from running if it’s located on the script server. This will avoid potentially wacky behavior that might result from various scripts running on the server.

Second Life Sound Issues

April 24, 2008 · Filed Under Second Life · Comment 

I’ve encountered an interesting limitation with sound in Second Life. You can only play a single sound from each script at any given time. If you have a script where you’d like to play a looping background sound and then play separate sounds based on events, you can’t. You are limited to a single sound playing at one time for each script. You can define whether additional sounds should cut-off and replace the current sound or should be queued to play after the current sound, but it’s only one at a time.Why the limitation? I could see limiting to 16, 8, or even 4 simultaneous sounds per script. If the concern is flooding the client with sounds, then that could be addressed by defining an overall limitation in the client, which I would hope exists already. This limitation simply forces anyone wishing to create a sound rich environment to create additional scripts for each sound. Inefficient.

Also, why are their separate functions for llPlaySound() and llLoopSound()? These should be a single function with an addition boolean parameter to define whether the clip loops. The same applies to llTriggerSound(). A boolean parameter defines whether the sound follows the prim it’s attached to or remains at the location it was created at. The new function could look like this, with the two new parameters (loop and follow) being optional and defaulting to false for backward compatibility.

llPlaySound(string sound, float volume, integer loop, integer follow)

Second Life Simple Data Storage

April 24, 2008 · Filed Under Second Life · Comment 

In creating scripts for Second Life, I’ve tried to keep the scripts as portable and re-usable as possible. At the most basic level, this means creating a separation of code and data. For scripts that are used in a limited number of prims, this can be as simple as setting customizable variables at the top of the script. For scripts that are going to be used in many prims, this system requires maintaining a unique copy of each script in each prim. If your base script is updated to fix a bug or add a feature, you’ll need to update each script by hand or overwrite the script in prim and reset the custom variables. Both options are prone to error.

For scripts used in many prims, storing the data for those variables in the prim’s description field can be an effective solution. This allows you to replace the script without impacting the custom data in each prim. The description field is limited to 127 characters, so this method is only useful with short length data. Also, since the description field can be publicly viewed in prim properties, this method should not be used to store private or sensitive data. On the plus side, this data can be updated dynamically using llSetObjectDesc().

When storing the value of a single variable in the description field, use this code to retrieve the value. If the type is anything other than a string, simply prefix the function with the data type. In this case, the variable type is a vector.

vector myVector; //declare variable type
myVector = (vector)llGetObjectDesc(); //read the description, a string by default, and convert to a vector

If you need to store multiple values, format the data in the description field as a list, such as “Someplace;<72,89,25>”, read the data and parse it. This example uses the semi-colon as a delimiter.

list description;
string locationName;
vector locationTarget;

description = llParseString2List(llGetObjectDesc(), [";"], [""] );
locationName = llList2String(description, 0);
locationTarget = (vector)llList2String(description, 1);

I have found this method to be very effective and efficient for scripts that contain a limited amount of custom data. To store larger amounts of data, you’ll need to use a notecard or data store external to the prim.