Self Upgrading Script
In some of my projects, I've had a number of prims that each needed the same script. When changes needed to be made to the script, however, it became rather annoying to go through every object, remove the existing script, and copy in the new one.
One way to remedy the problem is with a "manager" object and scripts to manage the numerous prims that must be keep up-to-date, but personally I wasn't thrilled with that solution, especially when I was in the habit of regularly linking and unlinking all the prims. Instead, I wanted a solution where I could drop the new script from inventory onto each of the required prims and have them upgrade themselves (by removing the old version).
So here is the solution I wrote. This code is added to the script to be kept upgraded; it runs as soon as it is dropped on the target prim.
upgrade() {
// Simple upgrade script; remove all other scripts with the same name as
// myself. ASSUMPTION: No spaces in the name (ie, the only space will be
// between the core name and the auto-generated "version" number).
// get my name
string me = llGetScriptName(); // full name of this script
list parts = llParseString2List(me, [" "], []);
string name = llList2String(parts, 0); // name without any trailing number
// search all scripts in inventory for those starting with the same name
integer n = llGetInventoryNumber(INVENTORY_SCRIPT);
while (n-- > 0) {
string item = llGetInventoryName(INVENTORY_SCRIPT, n);
if (item != me && 0 == llSubStringIndex(item, name)) {
// remove scripts with same name (except myself, of course)
llRemoveInventory(item);
}
}
}
default {
state_entry() {
upgrade();
// rest of your script's startup code
}
}
It isn't entirely robust, but (with a few minor restrictions on script naming) it serves my purpose. And it is relatively small, so I don't have any serious worries of it getting in the way of memory limits. This may not be a solution for everyone, but you might find it useful with a few tweaks of your own.
-= Update from Jippen Faddoul=-
This one isn't quite as flexable, but it assumes (usually correctly) that you are not starting off with several copies of the same script in the prim, but just 1 copy of the script to be updated.
Its a bit cleaner to put in your code, and will use less memory, since it doesn't need to deal with lists at all.
upgrade() {
//Get the name of the script
string self = llGetScriptName();
// Find out if the script ends in " 1"
// This rarely happens unless the script was copied in. ~.^
integer find = llSubStringIndex(self," 1");
// IF, and only if we find that this ends in " 1", start the update code.
if(find != -1) { llRemoveInventory(llDeleteSubString(self,find,-1)); }
}
default {
state_entry() {
upgrade();
// The actual script starts here.
}
}
-= Update from Cron Stardust=-
I found that the upgrade capabilities of these two cool scripts was sadly limited to requiring no spaces in the name, and/or only removing the un-numbered edition allowing only one upgrade before going back to requiring manual work. So I decided to mess with it myself:
Self Upgrading Script Enhanced
Cron