SL Updating Scripts
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.
- Avatar to Server: hey server, broadcast update request to region
- Server to Region: if you can hear me, it’s time to update
- Client to Server: hey server, please send me this script
- 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 Phantom Collisions
I’ve been given the opportunity to do some coding for Second Life. Before I started, I was presented with a number of horror stories about the Linden Scripting Language (LSL). While it’s not as bad as a thought it might be, there are certainly some oddities, some due to the language itself and some due to seemingly arbitrary limitations of the environment.
The first major issue that I ran into involved the detection of collisions with phantom prims. The project was a guided transportation system in which a vehicle would be provided a direction (vector) based on hidden prims that it collided with in the environment. The hidden prims providing the direction are transparent, so they cannot be seen in the environment. They are also phantom, since we didn’t want avatars blocked by invisible objects and becoming confused. However, no collision events (collision nor collision_start) are triggered in the vehicle. In this case, I’m using a vehicle, but the same applies to any prim or set of linked prims. By default, collisions with phantom objects are not detected by either object. Collisions can be detected by the phantom object with the inclusion of this function.
llVolumeDetect(TRUE);
However, this only allows collisions to be detected by the phantom prim and not by the vehicle that needs the information. The non-phantom prim will not detect collisions with phantom prims under any conditions. This meant that the vehicle pulling the new direction from the phantom prim was out of the question. Since the phantom prim could detect the collision, it must be the one to act.
collision_start(integer total_number)
{
llWhisper(channelNumber, message);
}
At the start of the collision, the phantom prim broadcasts the message on a non-0 channel. Using a non-0 channels helps to cut down on chat spam. In this case, I also used llWhisper, since the listening vehicle is moving slowly and will certainly be within 10 meters. llSay sends the message 20 meters, where it might be picked up by more vehicles.
In order to keep the chat to a minimum and ensure that only the vehicle involved in the collision acted upon the message, there are a number of other techniques used as well. The colliding objects all have the same name, so I can use a collision filter to ensure that only collisions with specifically named prims are detected.
llCollisionFilter(vehiclePrimName, NULL_KEY, TRUE);
While the collision event is fired continuously during the collision between two prims, the collision_start event is supposedly only fired once at the beginning of the collision. That certainly doesn’t appear to be the case, since collision_start is being fired multiples times as well. In order to limit this to a single event, get the key of the colliding object and only fire the event of the key is different from the last key. I also set a timer to clear the last key, so that future collisions with the same object will be effective, after 15 seconds in this case.
collision_start(integer total_number)
{
currentKey = llDetectedKey(0);
if ( currentKey != lastKey )
{
llWhisper(chatChannel, (string)currentKey + ";" + message);
lastKey = currentKey;
llSetTimerEvent(15);
}
}
timer()
{
lastKey = NULL_KEY;
llSetTimerEvent(0);
}
On collision with a specifically named prim if there was no collision with that prim in the last 15 seconds, the message is whispered on a non-0 channel. Of course, you will need to ensure that the vehicle is listening for the message on the same channel. I also pass the key of the colliding object, so that any object receiving the message can validate the message was intended for it.
This solution is a bit of a kludge, but it produces the desired result.


