Dataserver-Get a Notecard line help needed please
|
Marc Prudhomme
Registered User
Join date: 28 Nov 2005
Posts: 10
|
11-30-2005 10:31
I am very much a beginner and and trying to get a script that reads data from a 2 line notecard then stores each line as a seperate variable for use in something else. The first line is an avatar key and the second is a channel number.
I have been pleaying with an example script off the wikki and so far only trying to get the first line (the key) read and then said so I know it was read and is correct. I have no idea what I am mucking up but the key this thing says is not what is on the card and futhermore is different every time the script is reset.
Any and all help will be immensly appreciated
script code
string gName = "Settings"; // name of a notecard in the object's inventory integer gLine; // current line number key gQueryID; // id used to identify dataserver queries string AVKey; integer Channel; string temp; default { state_entry() { gQueryID = llGetNotecardLine(gName, gLine); // request first line // gLine++; // increase line count }
dataserver(key query_id, string data) { if (query_id == gQueryID) { if (data != EOF) { // not at the end of the notecard AVKey = llGetNotecardLine(gName, gLine); llSay(0, AVKey); // output the line return; // request next line // gLine++; // increase line count } } } }
Notecard 4c77b4fd-042f-4478-9ce9-a8884e5b69bd 47896352
|
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
|
11-30-2005 11:18
Firstly, Marc - Welcome to SL, and congrats on your first post Secondly, when posting code to the forums you can wrap it in [ PHP ] and [ /PHP ] tags to prevent the forum software from butchering it. thus: string gName = "Settings"; // name of a notecard in the object's inventory integer gLine; // current line number ... ... if (data != EOF) { // not at the end of the notecard AVKey = llGetNotecardLine(gName, gLine); llSay(0, AVKey); // output the line ... ... your problem here is that inside the dataserver event, the av key is passed in as the second parameter ( data), so you should be saying AVKey = (key)data;llGetNotecardLine returns the new query id, so you want to repeat what you did in state_entry by saying gQueryID = llGetNotecardLine(gName, gLine); again. The example code you had is great for multi-line reads, but for just two lines see if this makes sense to you... string NotecardName = "Settings"; // name of a notecard in the object's inventory key QueryID; // id used to identify dataserver queries
string AVKey; integer Channel;
default { state_entry() { AVKey = NULL_KEY; // reset the AVKey to a blank key, so that the dataserver event knows we are on the first line QueryID = llGetNotecardLine(NotecardName, 0); // request first line }
dataserver(key query_id, string data) { if (query_id == QueryID) // make sure this is our event, not some other script's { if (data == EOF) // at the end of the notecard - this shouldn't happen llOwnerSay("Error reading notecard: " + NotecardName); else if (AVKey == NULL_KEY) // we must have been reading line 0 { AVKey = (key)data; QueryID = llGetNotecardLine(NotecardName, 1); // request second line } else // otherwise, we have just read the second line (line number 1) { Channel = (integer)data; // now do whatever it is we wanted these lines for in the first place llListen(Channel, "", AVKey, ""); // in this example, listen for the specifed av, on the specifed channel } } } listen(integer channel, string name, key id, string message) { // whatever...... } }
|
Marc Prudhomme
Registered User
Join date: 28 Nov 2005
Posts: 10
|
11-30-2005 12:43
TYVVM!!!! You are a godsend!!! Yes it does make sense. Leave it to me to complicate things unnecissarily LOL. Bless You Bless You Bless You (choose appropriate diety or none) 
|
Owner Maltese
Registered User
Join date: 13 Sep 2005
Posts: 65
|
12-01-2005 04:46
Okay, I learn by example, and that was a great example. To get this clear in my head, if there were more lines to read, it would be simple to make it increment lines by making the single change below string NotecardName = "Sample"; // name of a notecard in the object's inventory key QueryID; // id used to identify dataserver queries
string AVKey; integer Channel; integer qdata //<--- added variable to increment
default { state_entry() { qdata = 0; AVKey = NULL_KEY; // reset the AVKey to a blank key, so that the dataserver event knows we are on the first line QueryID = llGetNotecardLine(NotecardName, qdata); // request first line }
dataserver(key query_id, string data) { if (query_id == QueryID) // make sure this is our event, not some other script's { while (data !== EOF) // <-- change this to the statement "while not equal to eof". { if (AVKey == NULL_KEY) // we must have been reading line 0 { AVKey = (key)data; QueryID = llGetNotecardLine(NotecardName, qdata); // request second line } else // otherwise, we have just read the second line (line number 1) { // now do whatever it is we wanted these lines for in the first place llSay(0,AVkey); // in this example, just say the line ++qdata //<-- increment the data } llSay(0,"All gone!"); //<-- Alert EOF } } }
Did I get it?? Am I catching on?
|
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
|
12-01-2005 05:40
(Thanks for the kind words, guys - they put the pleasure into helping others) Owner, you're close - just be aware that you will need to call llGetNotecardLine for each and every line to be read - and each one is going to fire a seperate dataserver event - so we can't use a while loop here. Welcome the the asynchronous world! To illustrate, I've removed the AVKey part completely - just to focus on the "read all lines until the end" bit. Notice that each time we succesfully read a line, we increment the line counter (as you were doing), and then call llGetNotecardLine again with the new value. Rinse and repeat until we hit EOF. string NotecardName = "Sample"; // name of a notecard in the object's inventory key QueryID; // id used to identify dataserver queries
integer LineNumber //<--- added variable to increment
default { state_entry() { LineNumber = 0; QueryID = llGetNotecardLine(NotecardName, LineNumber); // request first line } dataserver(key query_id, string data) { if (query_id == QueryID) // make sure this is our event, not some other script's { if (data !== EOF) // <-- if we got data { llOwnerSay("Line #" + (string)LineNumber + " : " + data); ++LineNumber //<-- increment the line number QueryID = llGetNotecardLine(NotecardName, LineNumber); // request next line } else // otherwise, we have just read the second line (line number 1) llOwnerSay("All gone!"); } } } (hope I got it right - can't get in-world from work  )
|
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
|
12-01-2005 08:05
silly question, why not but the data on the same line? something like "key~channel" string NotecardName = "Sample"; // name of a notecard in the object's inventory key QueryID; // id used to identify dataserver queries
list AvKeys; list Channels;
integer LineNumber = 0;
default { state_entry() { if(!LineNumber)//don't really want to reread the notecard on a state change only on script (re)start. QueryID = llGetNotecardLine(NotecardName, LineNumber); // request first line } dataserver(key query_id, string data) { if (query_id == QueryID) // make sure this is our event, not some other script's { if (data != EOF) // <-- if we got data { AvKeys += llGetSubString(data,0,35); Channels += (integer)llGetSubString(data,37,-1); QueryID = llGetNotecardLine(NotecardName, ++LineNumber); // request next line (we increment at the same time, saves 6 bytes). } else // otherwise, we have just read the second line (line number 1) llOwnerSay("Notecard all read!"); } } }
_____________________
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
|
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
|
12-02-2005 03:07
From: Strife Onizuka silly question, why not but the data on the same line? something like "key~channel" Nice! Replacing 2 dataserver requests with 1 request and some string manipulation. Far more efficient - TY
|
Marc Prudhomme
Registered User
Join date: 28 Nov 2005
Posts: 10
|
12-02-2005 05:57
From: Strife Onizuka silly question, why not but the data on the same line? something like "key~channel" string NotecardName = "Sample"; // name of a notecard in the object's inventory key QueryID; // id used to identify dataserver queries
list AvKeys; list Channels;
integer LineNumber = 0;
default { state_entry() { if(!LineNumber)//don't really want to reread the notecard on a state change only on script (re)start. QueryID = llGetNotecardLine(NotecardName, LineNumber); // request first line } dataserver(key query_id, string data) { if (query_id == QueryID) // make sure this is our event, not some other script's { if (data != EOF) // <-- if we got data { AvKeys += llGetSubString(data,0,35); Channels += (integer)llGetSubString(data,37,-1); QueryID = llGetNotecardLine(NotecardName, ++LineNumber); // request next line (we increment at the same time, saves 6 bytes). } else // otherwise, we have just read the second line (line number 1) llOwnerSay("Notecard all read!"); } } }
This confuses me as it applies to what I am trying to do. this is a settings card in which in effect a second owner is being set. How do we know where to set the cutoff for AVKey read? are all keys the same length? Sorry I am very much a beginner.
|
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
|
12-02-2005 06:17
From: Marc Prudhomme This confuses me as it applies to what I am trying to do. The code we already have for you is fine for your application where you only wanted one key and one channel. My second example, and Strife's, are based on reading an unknown number of lines from a card until we hit the end. My example just reads all the lines and displays them (just to show how it's done.) Strife's example combines your requirement (key + channel) and Owner's requirement (multiple lines). To specifically answer your question - Yes, all keys are 36 characters long.Using Strife's optimisation based on this means that your script would only have to wait for the dataserver once - which not only speeds up the code, but simplifies the logic quite a bit as well. As an excersise (if you want) try editing my first example to include his technique. Remove any logic that is no longer needed to make it as simple as possible. Post your result here, and we'll (gently  ) crit it.
|
Joey Soothsayer
Registered User
Join date: 25 Oct 2005
Posts: 0
|
01-02-2006 02:37
Im working on something similar. i need it to read off notecard lines at regular intervals, so i need to add a timer, but i cant get the timer to work right. it either wont compile, or wont advance the line number, or retrieves a key to the data, but not the actual data itself. gTime is going to be the line 0 and every other line which contains the length of the video. string gName = "clips"; // name of a notecard in the object's inventory integer gLine = 1; // current line number key query1; // id used to identify dataserver queries key query2; integer gTime;
default { state_entry() { llSay(0, "Click to play video"); query1 = llGetNotecardLine(gName,0); } touch_start(integer num_detected) { ++gLine; query2 = llGetNotecardLine(gName,gLine); } dataserver(key query_id, string data) { if (data != EOF) { if (query1 == query_id) { gTime = (integer)data; } if (query2 == query_id) { llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_URL, (string)data]); llOwnerSay("Now playing clip " + (integer)gLine); ++gLine; query2 = llGetNotecardLine(gName, gLine); } } else { gLine = 1; llSay(0, "End of movie."); } } }
|