Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Empty notecard funkyness

Eata Kitty
Registered User
Join date: 21 Jan 2005
Posts: 387
09-07-2005 05:56
I was writing some sanity checking code to ensure that a notecard has data in it before we try to read from it and found some weird behaviour.

First, a newly created notecard will not be recognised by scripts until it has been opened and saved. I imagine this is by design but it's still slightly unusual.

Second the dataserver will not return an EOF for a totally empty notecard! It will actually pass and attempt to do something with no data. I'm not exactly sure how far this goes but if you add the data into a list you will get a totally empty list with one item in it.

The workaround is to actually check the length of what is returned from the notecard before we do anything with it:

CODE
 if(llStringLength(data) > 0)


Here's a script to test this with, remember you have to save the notecard first or you will encounter the first problem I mentioned.

CODE

// This is the name of the notecard to read items from
string itemDataNotecard = "Test Notecard";
// Required to read the notecard properly
integer notecardLine;
key currentDataRequest;

list TestList = [];

default
{
touch_start(integer num_detected)
{
notecardLine = 0;
currentDataRequest = llGetNotecardLine(itemDataNotecard, notecardLine);
}

dataserver(key query, string data) {
if (query == currentDataRequest) {
currentDataRequest = ""; // Prevent a bug that occurs with dataserver events.
if (data != EOF) {
// Read the current item
TestList += data;
notecardLine++;
// Get the next line
currentDataRequest = llGetNotecardLine(itemDataNotecard, notecardLine);
} else {
// Finished
state Output;
}
}
}
}

state Output
{
state_entry()
{
llOwnerSay("List data: {" + llDumpList2String(TestList, " + ") + "}");
llOwnerSay("List length: " + (string)llGetListLength(TestList));
if (TestList == [])
{
llOwnerSay("Client list is empty");
}
else
llOwnerSay("List contains data");
}
}
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
09-07-2005 06:37
I've noticed this as well. It's a weird "feature". Don't ask me.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
a lost user
Join date: ?
Posts: ?
09-07-2005 15:44
From: LSL Wiki
If the requested line is past the end of the notecard, the dataserver event will return the constant EOF ("End Of File";) string.


So it reads the blank line and returns it via the dataserver. Then when it attempts to read the line after the blank line it determines that it has reached the end of the file. Note that a blank line is still a line of data, it just doesn't contain any information except for a linefeed/carriage return in the case of multiple blank lines. It has to past the last line to have the EOF message thrown to the dataserver.

What you could do is check to see if the data is not empty and increment a counter for lines with information, then if you reach the end of the file and there are only empty/blank lines, you know that the notecard contains no data:
CODE

dataserver(key query, string data)
{
if(data != EOF)
{
// Not at the end of notecard yet...
if(data != "")
not_blank++; // Increment counter for non-blank lines

llGetNotecardLine(gCard, gLine); // Get next notecard line
gLine++; // Increment notecard line number for next notecard read
}
else
{
// At end of notecard now...
if(not_blank == 0)
llSay(0, "The notecard was empty.");
}
}
InuYasha Meiji
Half Demon
Join date: 14 Mar 2005
Posts: 127
I thank you all for helping me too
07-22-2006 02:06
I've also been Reading this and now understand, but it is amazing how a person can get some of this but miss one little thing I ned to do what I want with it. I was wondering how can I without putting all that notecard into memory. (I have a huge notecard, and don't want to use all my 16k worth of script mem), to read a single line of the notecard, touch the item, and read the next line, and when done, just start over at the top?

I have a notecard full of quotes I want to get a single line each time someone touches the item.

I figured I'd ask, since the topic covers so much of what I needed.

Thanks, InuYasha Meiji
Angela Salome
Registered User
Join date: 6 Oct 2005
Posts: 224
07-22-2006 03:01
From: InuYasha Meiji
...how can I ... get a single line each time someone touches the item.


Something like this:
CODE

touch_start (integer touches)
{
llGetNotecardLine(gCard, gLine);
}
Adriana Caligari
Registered User
Join date: 21 Apr 2005
Posts: 458
07-22-2006 03:03
From: InuYasha Meiji
I've also been Reading this and now understand, but it is amazing how a person can get some of this but miss one little thing I ned to do what I want with it. I was wondering how can I without putting all that notecard into memory. (I have a huge notecard, and don't want to use all my 16k worth of script mem), to read a single line of the notecard, touch the item, and read the next line, and when done, just start over at the top?

I have a notecard full of quotes I want to get a single line each time someone touches the item.

I figured I'd ask, since the topic covers so much of what I needed.

Thanks, InuYasha Meiji


1st use

llGetNumberOfNotecardLines to determine how many lines you have

http://secondlife.com/badgeo/wakka.php?wakka=llGetNumberOfNotecardLines


Then just change the notecardline in

llGetNotecardLine( notecard_name,notecardline )

to read a line

Eg

integer lines = llGetNumberOfNotecardLines( "card" ) ;
integer rline = ( integer )llFrand( lines )
my_query = llGetNotecardLine( "card",rline );
_____________________
Maker of quality Gadgets
Caligari Designs Store
Joannah Cramer
Registered User
Join date: 12 Apr 2006
Posts: 1,539
07-22-2006 05:48
From: Adriana Caligari
integer lines = llGetNumberOfNotecardLines( "card" ) ;
integer rline = ( integer )llFrand( lines )
my_query = llGetNotecardLine( "card",rline );

That won't work ^^;;; llGetNumberOfNotecardLines() returns the answer in dataserver() event, the return value is just the query ID ... so more like
CODE

key query = NULL_KEY;
integer lines = 0;

default {

state_entry() { query = llGetNumberOfNotecardLines( "card" ); }

dataserver( key QueryID, string Data ) {

if( QueryID == query ) {

lines = (integer)Data;
query = NULL_KEY;
if( lines > 0 ) state ready;
}
}
}

state ready {

touch_start( integer ContactsTotal ) {

integer rline = ( integer )llFrand( lines )
query = llGetNotecardLine( "card", rline );
}

dataserver( key QueryID, string Data ) {

if( QueryID == query ) {

llSay( 0, Data );
query = NULL_KEY;
}
}
}
InuYasha Meiji
Half Demon
Join date: 14 Mar 2005
Posts: 127
Thanks so much I really apreciat that.
07-22-2006 20:24
Looking at it, I can't believe it was that simple. I really apreciate it. I looked all around in the forums and wiki, asked other topics and everything, but I just got errors all day. I literally spent all day on it and got nothing done.

You helped me finish my day on a high note. Thanks again see ya in game.

-InuYasha Meiji