LSL LinksetData is a relatively new addition to Second Life scripting that veteran devs say can powerfully transform interactive experiences in Second Life.
To illustrate how, longtime scripter Grace Ling, creator of the popular roleplay app, Really Needy HUD, explains how it's used in her roleplay system -- and how it can be used in a location-finding game.
Read on for her tutorial!
I am sure some of you have heard of the release of LinksetData in Second Life in November last year, which has been hailed as a powerful upgrade to scripting capabilities in SL. How big of a deal is it? It’s been compared to how rigged mesh changed avatars, and there are debates in the scripter community on it, while some people say it should have come a decade earlier.
While I have more than 10 years of scripting experience in SL, I have only recently dabbled in LSD so am by no means an expert. This tutorial assumes you have some basic to intermediate knowledge of LSL scripting and have scanned through the official wiki entry on it already.
I am going to use 2 examples in this tutorial:
- How I used LinksetData for a roleplay HUD system I developed.
- How LinksetData could be used for a mini-game to reward users for exploring a sim.
Historically, when scripters in SL need to store more data for more complex applications, they would find the script running out of memory. They had a few options, which were not so ideal :
- Store the data on an external server outside Second Life (which requires costs and technical skills which is a barrier of entry for many)
- Make use of some hacks like storing the data in the object Description field, or in notecards
- Use Experience Tools (but this requires the sim-owner to have Premium account etc.)
With LinksetData, the data can now be persistently stored inside the object. It is persistent because it is able to survive script resets and object transfers. Assuming I use up to half of the available memory of a script for storing data, LinksetData allows me to save 4 times this amount of data inside the object.
Example 1
Use-case: Maintaining a list of pregnancy food aversions or cravings for a roleplay HUD.
With more than 40 types of food that could potentially cause nausea or heartburn and 30 possible type of cravings, this would normally consume a lot of memory to save these lists in my script.
❶ I can write a script to let the user install potential aversions/cravings in their Really Needy HUD, and have the script auto-delete itself after installation.
For example, these 2 lines will save the list of foods/drinks that could trigger nausea and heartburn into the LinksetData of the Really Needy HUD.
llLinksetDataWrite("nausea_list","FRIED EGG,CHEESE,FISH,COFFEE, ALCOHOL,BEER");
llLinksetDataWrite("burn_list","ORANGE,POMELO,LEMON,COFFEE,
CAPPUCCINO,LATTE,EARL GREY,MOUNTAIN DEW");
Essentially, the LinksetData functions revolve around “Key Value Pairs” (KVP), which is a key that goes with a value.
The key is ‘nausea_list’ and the value I stored is a string “FRIED EGG, …. BEER”.
❷ Another script in the HUD can read the data whenever the user consumes something and compare if the item consumed matches with any item in the list saved in the LinksetData of the HUD.
string temp = llLinksetDataRead("nausea_list");
list NAUSEA_LIST = llCSV2List(temp);
integer length = llGetListLength(NAUSEA_LIST);
integer index;
while (index < length) // this is a loop to check for each list element
{
string phrase = llList2String(NAUSEA_LIST,index);
[insert code to check whether phrase matches with name of food];
++index;
}
Benefit: This allows me to separate the data from the script so the script can just read the data when it needs to, rather than storing in script memory all the time. It also allows me to give choices to my users on whether they wish to have a long or short list of aversions or none at all.
Example 2
Use-case: Track the locations in the city that a player has visited in a medieval city sim (eg. inn, armory, alchemist) using keywords. This could be used to reward users for exploring a sim, or to support storytelling, or to complement with NPC chatbots for a more interactive experience.
This data could be stored in a HUD that the player is wearing using LinksetData, instead of storing on an external server. It could also be stored in the sim Experience as an alternative. A combination of both LSD and Experience is also possible.
By checking for the existence of certain keywords in the string associated with the History key, your HUD will be able to tell if the player has visited a particular sim location.
Say the Player visits the inn and talks to the innkeeper who promised the Player that he would give the Player a treasure map in return for rescuing his daughter. Record it by saving the keyword “INNKEEPER PROMISE” under a “History” key.
Like this: llLinksetDataWrite("History","INNKEEPER PROMISE");
However, you will need to check first if there is already a History key value in the HUD to avoid overwriting any existing data accidentally. If there isn’t any existing key with that name, the Read function returns an empty string.
Hence you could do the check like this:
string temp = llLinksetDataRead("History");
if (temp=="")
{
llOwnerSay("No History data found. Creating new record.");
llLinksetDataWrite("History","INNKEEPER PROMISE");
}
If it is not an empty string, then you would want to add the keyword “INNKEEPER PROMISE” to the History data.
But if the Player has already visited the Inn previously, you don’t want to add the same keyword again. So you need to check if the keyword is already one of the keywords recorded under the History key.
You can use the llSubStringIndex function to check if one string is a substring of another string.
integer found = llSubStringIndex(temp,"INNKEEPER PROMISE");
If the value returned is -1, it means the second string cannot be found inside the first string.
This is putting it all together:
string temp = llLinksetDataRead("History");
if (temp=="")
{
llOwnerSay("No History data found. Creating new record.");
llLinksetDataWrite("History","INNKEEPER PROMISE");
}
else // there is already data saved in History
{
integer found = llSubStringIndex(temp,"INNKEEPER PROMISE");
if (found==-1) // not found. Hence, append keyword to the History
llLinksetDataWrite("History",temp+",INNKEEPER PROMISE");
else llOwnerSay("The Innkeeper previously promised you a reward.");
}
As a concluding note to this tutorial, there are also more secure versions of the Read and Write functions which allows you to password protect the data you are storing. Hope this tutorial was helpful.
Find out more on Grace's Really Needy HUD site.
Comments