Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Read from Notecard test system: Any thoughts

Foolish Frost
Grand Technomancer
Join date: 7 Mar 2005
Posts: 1,433
03-19-2005 09:48
Hullo all!

This was a system for accessing a NoteCard file in an object. It's two scripts, with the main processing script handing off the NoteCard data requests to another script.

Both scripts have to be in the same prim, and communicate by choosing "channels" to talk on.

I'll let the code speak for itself and we can talk about it after...

None of this code has been compiled, as I'm at work and unable to login for testing... Anyone ever thought of making an external "code tester"?

DataUser Script:
CODE
string DataCard = "DataCard";
integer LineNumber = 0;

integer ReturnDataGo = 0;
integer ReturnDataLine;
string ReturnDataString;


// --------------------------------------------------
// Function to trigger string data from line number
// --------------------------------------------------
GetNoteData(integer gsdline, string gsddata) {

llMessageLinked(llGetLinkNumber(), gsdline+100000, (string)gsddata, "");

// wait for datareturn
do
{
llSleep(.5)
} while (ReturnDataGo = 0);

ReturnDataGo = 0;

// -------------------------------------
// Recieve data from datareader script
// -------------------------------------

link_message (llGetLinkNumber(), RDataChannel, RDataString, DataKey)
{


if (RDataChannel>199999 && RDataChannel<300000)
{

ReturnDataLine = RDataChannel - 200000;
ReturnDataString = RDataString;
ReturnDataGo = 1;

} // End if


} // End link_message

}
// --------------------------------------------------


default
{

GetNoteData(0, DataCard)
llSay(0, ReturnDataString);
GetNoteData(1, DataCard)
llSay(0, ReturnDataString);
GetNoteData(2, DataCard)
llSay(0, ReturnDataString);

} // End default


DataReader Script:
CODE
integer DataChannel;
string DataString;
string DataKey; //null string. Not used.

// ---------------------------------------------------------
// This code is made to make the process
// of using NoteCards for data a much
// simpler affair.
//
// The DataChannel variable taken from the message
// is coded to ignore channels 0-99999, and to otherwise
// convert the DataChannel into a line number for reading
// data by subtracting 100000 from it.
//
// Response data is sent back on a DataChannel 100000 higher.
// That means a request for line 24 would be sent as 100024,
// and would be sent back on channel 200024
//
// Example: llMessageLinked(llGetLinkNumber(), line requested + 100000, "NoteCardName", "")
// ---------------------------------------------------------

// --------------------------------
// begin datacard processing code
// --------------------------------

default
{


link_message (llGetLinkNumber(), DataChannel, DataString, DataKey)
{


if (DataChannel>9999 && DataChannel<200000)
{


llGetNotecardLine((DataChannel-100000), DataString);


} // End if


} // End link_message


dataserver(key query_id, string data)
{

// Send the notecard data
llMessageLinked(llGetLinkNumber(), DataChannel+100000, (string)data, "");

}


} // End default
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
03-19-2005 11:16
From: Foolish Frost

DataUser Script:
CODE
string DataCard = "DataCard";
integer LineNumber = 0;

integer ReturnDataGo = 0;
integer ReturnDataLine;
string ReturnDataString;


// --------------------------------------------------
// Function to trigger string data from line number
// --------------------------------------------------
GetNoteData(integer gsdline, string gsddata) {

llMessageLinked(llGetLinkNumber(), gsdline+100000, (string)gsddata, "");

// wait for datareturn
do
{
llSleep(.5)
} while (ReturnDataGo = 0);

ReturnDataGo = 0;

// -------------------------------------
// Recieve data from datareader script
// -------------------------------------

link_message (llGetLinkNumber(), RDataChannel, RDataString, DataKey)
{


if (RDataChannel>199999 && RDataChannel<300000)
{

ReturnDataLine = RDataChannel - 200000;
ReturnDataString = RDataString;
ReturnDataGo = 1;

} // End if


} // End link_message

}


I think you may be confusing how to use LSL's event based communications interface.
You cannot define an event within a function, only within a state. Events are not blocking functions, you cannot call them directly, they are triggered by the virtual machine only. That while() loop will never complete because ReturnDataGo will never be 1, scripts are not multi-threaded.

Here's something that might work for you:
CODE
string DataCard = "DataCard";
integer LineNumber = 0;

integer ReturnDataGo = 0;
integer ReturnDataLine;
string ReturnDataString;

// This function requests string data from the note reader
// and returns immediately, link_message will be triggered
// with the return value.
requestNoteData(integer gsdline, string gsddata)
{
llMessageLinked(llGetLinkNumber(), gsdline+100000, (string)gsddata, "");
}

default
{
state_entry()
{
requestNoteData(0, DataCard);
requestNoteData(1, DataCard);
requestNoteData(2, DataCard);
}

// The link_message event, when is triggered
// by the virtual machine, has the link number of the
// script that called llMessageLinked, and the integer, string and key
// that that script passed to llMessageLinked in 'RDataChannel', 'RDataString', and 'DataKey' respectively.
// It will be called three times, since we requested three lines in state_entry.
link_message(integer sender, integer RDataChannel, string RDataString, key DataKey)
{
// Im assuming the sender sends an integer between 199999 and 300000 through llMessageLinked...
if (RDataChannel>199999 && RDataChannel<300000)
{
ReturnDataLine = RDataChannel - 200000;
ReturnDataString = RDataString;
ReturnDataGo = 1;
llSay(0, ReturnDataString);
}
}
}


The DataReader Script looks like it will work fine, save for this line:

From: someone
DataReader Script:
CODE
link_message (llGetLinkNumber(), DataChannel, DataString, DataKey)


You have to declare link_message like this:
link_message(integer someName1, integer someName2, string someName3, key someName4)

Because link_message acts like a function that the virtual machine (the thing that runs scripts) calls.

You dont declare your own functions like this:
CODE
foo(1, 2) {
// Code here
}

right? You declare them like this:
CODE
foo(integer num, integer anotherNum) {
// Code here
}

and expect the caller to provide the values for num and anotherNum.

==Chris
_____________________
October 3rd is the Day Against DRM (Digital Restrictions Management), learn more at http://www.defectivebydesign.org/what_is_drm
Foolish Frost
Grand Technomancer
Join date: 7 Mar 2005
Posts: 1,433
03-19-2005 11:28
Now wait, don't we need a safety-net in case the other script is delayed? There is nothing here to make sure the code has actually gotten a return value from link_message yet before continuing on.

That was the reason for the ReturnDataGo variable. when it turns 1, something was returned. otherwise, we're still waiting for the return message from the other script.

Or am I thinking too hard?
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
03-19-2005 11:46
From: Foolish Frost
Now wait, don't we need a safety-net in case the other script is delayed? There is nothing here to make sure the code has actually gotten a return value from link_message yet before continuing on.


Ah, that's the point of states. In this case, you might want to have a state where the notecard reading is in progress, then switch to another one once it is done. If you do want a safety net case, call llSetTimerEvent in state_entry, reset it in link_message, and declare a timer event, that when called, does something to indicate that the reading script has timed out (taken too long to respond).

==Chris
Jack Lambert
Registered User
Join date: 4 Jun 2004
Posts: 265
03-19-2005 12:01
Chris described almost exactly how I do my notecard configs. States are the way to go here I think.

--Jack Lambert
_____________________
----------------------------
Taunt you with a tree filled lot? hahahahahahaha. Griefer trees! Good lord you're a drama queen. Poor poor put upon you.

-Chip Midnight
Foolish Frost
Grand Technomancer
Join date: 7 Mar 2005
Posts: 1,433
03-19-2005 17:15
From: Christopher Omega
Ah, that's the point of states. In this case, you might want to have a state where the notecard reading is in progress, then switch to another one once it is done. If you do want a safety net case, call llSetTimerEvent in state_entry, reset it in link_message, and declare a timer event, that when called, does something to indicate that the reading script has timed out (taken too long to respond).

==Chris



Explain states, in your parlance, to me... I would like to make sure I'm understanding you correctly...