Don't click here unless you want to be banned.

LSL Wiki : llGetNotecardLine

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are xcrawl107.alexa.com
key llGetNotecardLine(string name, integer line)

This function fetches line number of notecard name and returns the data through the dataserver event. The line count starts at zero. If the requested line is past the end of the notecard, the dataserver event will return the constant EOF ("End Of File") string. You can get the number of lines in a notecard with llGetNumberOfNotecardLines. The key returned by llGetNotecardLine is a unique identifier which will be supplied to the dataserver event as the queryid parameter.

name can be either a string containing the name of a notecard in the object's inventory, or a key pointing to a notecard (that can be anywhere and doesn't have to reside in the object). In the latter case. you should keep in mind that any time you edit and save such a notecard, it will get a new key.

If name is not a valid notecard, or if the notecard is empty, the object will print to the Script Errors/Warning window, "Couldn't find notecard NAME" where "NAME" is the name of the invalid notecard.

Note that lines longer than 255 characters will be truncated without any indication that this has been done.

Requests from notecards that contain embedded inventory items will always result in EOF, regardless of the line being requested.

Note: This function delays the script for 0.1 seconds.

Example:
// Read out a complete notecard from the object's inventory.
string gName;    // name of a notecard in the object's inventory
integer gLine = 0;        // current line number
key gQueryID; // id used to identify dataserver queries

default {
    state_entry() {
        gName = llGetInventoryName(INVENTORY_NOTECARD, 0); // select the first notecard in the object's inventory
        gQueryID = llGetNotecardLine(gName, gLine);    // request first line
    }

    dataserver(key query_id, string data) {
        if (query_id == gQueryID) {
            if (data != EOF) {    // not at the end of the notecard
                llSay(0, (string)gLine+": "+data);    // output the line
                ++gLine;                // increase line count
                gQueryID = llGetNotecardLine(gName, gLine);    // request next line
            }
        }
    }
}

/////
//  Generic Multi Notecard reader by Brangus Weir
//  Given freely and published on wiki.secondlife.com
//
// This script will read three note cards and store the results into 3 lists.
// It can be modified and extended to as many cards as you'd like to read. 
//
list gOneCard;  // All the lines from from the first card
list gTwoCard;    // All the lines from from the second card
list gThreeCard;   // All the lines from from the third card

string gsCardOneName = "One";  //Set these to the name of the inventory item.
string gsCardTwoName = "Two";
string gsCardThreeName = "Three";

//Temporary variables for processing
string g_sNoteCardName; // Name of the card to be read.
list g_lTempLines;  // The resulting data pushed into a list
integer g_iLine;    // The line count for the card reader
key g_kQuery;       // The key of thge card being read


initialize(string _action) {
    //Due to the execution order when using dataserver, this function sets the first card to 
    //be read, and the excetuion finishes when called again with the _action set to "finish".
    if (_action == "") {
        loadNoteCard(gsCardOneName);
    } else if (_action = "finish") {
        // All cards have been read into the lists... now you can do any kind of string
        // manipulations to get the data you need to set your script.
        // But here we will prove that the cards have been read with a loop
        integer end = llGetListLength(gOneCard);  
            // Don't be a noob scripter - evaluate end once 
                     //  for (i=0; i< LLGetListLength(gOneCard); i++) 
                     // is just so wrong and laggy! THINK and reduce lag.
        integer i;
        for (i = 0; i< end; i++)
            llSay(0, llList2String(gOneCard,i));
        end = llGetListLength(gTwoCard);
        for (i = 0; i< end; i++)
            llSay(0, llList2String(gTwoCard,i));
        end = llGetListLength(gThreeCard);
        for (i = 0; i< end; i++)
            llSay(0, llList2String(gThreeCard,i));
    }                
                              
}

loadNoteCard( string _notecard ) {
    g_lTempLines = []; //clear the temp lines
    g_sNoteCardName = _notecard;
    g_iLine =0;
    g_kQuery = llGetNotecardLine(g_sNoteCardName, g_iLine);  
    
}

notecardFinished(string _notecard){
    // Called at the end of each notcard as it is read. The temp results are stored
    // and the next card is commanded to be read.
    if (_notecard == gsCardOneName) {
        gOneCard = g_lTempLines;
        loadNoteCard(gsCardTwoName);
    } else if (_notecard == gsCardTwoName) {
        gTwoCard = g_lTempLines;
        loadNoteCard(gsCardThreeName);
    } else if (_notecard == gsCardThreeName) {
        gThreeCard = g_lTempLines;
        initialize("finish");  // Finally pass exection to finish the initialization.   
    }    
}

default
{
    state_entry()
    {
    }
    
    touch_start(integer num_det){
        initialize("");     
    }
     
    dataserver(key _query_id, string _data) 
    {
        if (_query_id == g_kQuery) {
            // this is a line of our notecard
            if (_data != EOF) {    
                // increment line count
                g_lTempLines += [_data];
                //request a next line
                g_iLine++;
                g_kQuery = llGetNotecardLine(g_sNoteCardName, g_iLine);
            } else {
             //The notecard has been read 
             //notify end of read
             notecardFinished(g_sNoteCardName);   
            }
        }
    }
}

Q: How do I write to a notecard?
A: You can't. The design of the asset system means that every time you change an asset, be it an object in-world, or an inventory item, you effectively create a new one, with a new key. This means that every time a change was made to a notecard, the asset server would have to create a new asset.

The reason this is bad is simple: load. When the database's load becomes too high, the entire system basically fails. The Lindens don't want that. Changing the asset system has been looked at, but it would evidently necessitate a fairly major rewrite of the entire database, and is not something that's likely to happen.

Fortunately, there are plans to create a seperate database storage system for scripts, though there isn't yet any projected release date for such a feature. Of course, data storage is not the only reason one might want to write to a notecard. The other potential use -- output to a notecard -- is not something the Lindens have plans for.

Q: What happens if I create a notecard, don't edit and save it, but place it in the object and then try to run llGetNotecardLine on it?
A: The same thing as if you passed an invalid name: the object will say, "Couldn't find notecard NAME" where "NAME" is the name of the invalid notecard. Nothing will be returned to the script, and it will be as if llGetNotecardLine was never called.

Q: So what do I do then? How does my script know what to do if there's no way to tell it whether or not the notecard is empty?
A: Try adding a timeout using a timer, or use a second object containing a listener to reply with a message indicating the notecard was empty or not present.

Q: Is there some way to get around the 255-character line limit?
A: No. The best you can do is to check the length of the resulting string in the dataserver event using llStringLength to see if it reaches the maximum, then from that, assume the line has been truncated. The problem with doing this is that your script can't actually do anything about it, save for suggesting to the user that they may wish to examine the line in question to determine if anything important is in there. Further, there's the very real possibility of false positives in non-truncated lines that just happen to be 255 characters long.

Q: So I guess that means there's no way to conclusively determine whether a line's been truncated, huh?
A: Nope, sorry.


Functions | Dataserver | Inventory
Comments [Hide comments/form]
Q: How do I write to a notecard?
A: You can't. The design of the asset system means that...


There is a simple enough solution to this problem. Copying an object out of inventory into the world creates a new UUID too, so clearly the system can handle some load. What is needed is a way to script edit a notecard many times, but only save the notecard infrequently, perhaps once every 5 minutes.

You would start an edit with an llBeginNotecardEdit() call, then you would call functions to seek, insert, and append text. When done, you would call llEndNotecardEdit(). If llEndNotecard has not been called by the same script in the last 5 minutes, then it commits the set of edits. If it has, then it delays until 5 minutes have passed.

A notecard editing system would significantly reduce the demand for access to external servers. If done right, such a system would reduce the load on SL, not increase it.
-- Point314 (2006-07-20 03:27:15)
Point314, it has to do with the asset server. Commiting things to this one central server causes load, so making scripts able to do so would be bad. It is better for the sims to have things like llHttpRequest and llEmail than for central assets to be modifiable by scripts.

The Lindens have commented on how some sort of scriptable database (per-object?) features will exist in the future.
-- KeknehvPsaltery (2006-07-20 16:50:52)
If you have multiple scripts in the same prim that use the dataserver, make sure you check the dataserver key! I got burned by this because I'd never actually read the dataserver event handler wiki page, and so didn't realize that the dataserver triggers *all* dataserver event handlers in the prim, not just the one in the script that caused it. (which should have been apparent if I'd thought about it a little bit, but I didn't).
-- NeoRebus (2006-08-20 20:14:19)
Attach a comment to this page: