Notecards
|
|
Alan Ajax
Registered User
Join date: 9 Aug 2006
Posts: 38
|
12-03-2006 19:29
Can someone please give me a code example of how to get config parameters from a notecard?
Thanks in advance
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
12-04-2006 04:22
Plenty of examples through out the forum. The basic's are a dataserver event. here is a relatively barebones example, ist based on Hank ramos's code I picked up when I first started in SL and I've used it ever since. how you format your notecard is really down to you, I use PARAMETER=VALUE pairs mainly for simplicity. The chanegd event means that the system will automatically reset if the owner is changed or the inventory has been updated. I use this to allow the system to automatically detect when I have edited the notecard. The timer event in the readConfig state helps prevent the script from locking up in the event of a dataserver event not happening for some reason. // basic DataServer // string notecard = "Configuration"; integer lineCounter; key dataRequestID;
integer Channel = 0; float Volume = 0.0; string Sound;
// // helper functions // GetParameters(string str) { // parameters are stored as // parameter=value
list ldata = llParseString2List(str, ["="], [""]); string command = llList2String(ldata,0); string value = llList2String(ldata,1); integer intvalue = (integer)value;
//llOwnerSay("Read " + command + " : " + value); if("Channel" == command) { Channel = intvalue; } else if("Volume" == command) { Volume = (float)value; } else if("Sound" == command) { Sound = value; } } ChangedStatus(integer change) { // Test for a changed inventory if (change & CHANGED_INVENTORY) { llResetScript(); } else if (change & CHANGED_OWNER) { llResetScript(); } }
// Used only for initialisation default { state_entry() { state ReadConfig; } // Should never be rezzed in this state so reset on_rez(integer num) { llResetScript(); } // if something has been updated reset changed(integer change) { ChangedStatus(change); } }
// Main State state Running { state_entry() { } changed(integer change) { ChangedStatus(change); } }
//-------------------------------------------------------------------------------- state ReadConfig { state_entry() { lineCounter = 0; integer itemtype = llGetInventoryType(notecard); if(INVENTORY_NOTECARD == itemtype) { dataRequestID = llGetNotecardLine(notecard, lineCounter); llSetTimerEvent(10); } else { llOwnerSay("Error - configuration notecard missing, Using defaults only!"); state Running; }
}
dataserver( key query_id, string data ) // read from the notecard { if(query_id == dataRequestID) { if (data != EOF) { if(llStringLength(data) > 3) { GetParameters(data); } lineCounter++; dataRequestID = llGetNotecardLine( notecard, lineCounter ); } else { llSetTimerEvent(0); state Running; } } } timer() { llOwnerSay("ERROR - Dataserver time out! aborting"); llSetTimerEvent(0); state Running; } // Should never be rezzed in this state so reset on_rez(integer num) { llResetScript(); } // if something has been updated reset changed(integer change) { ChangedStatus(change); } }
|
|
Alan Ajax
Registered User
Join date: 9 Aug 2006
Posts: 38
|
12-04-2006 06:42
Thanks! Exactly what I needed and more.
|
|
Zaphod Kotobide
zOMGWTFPME!
Join date: 19 Oct 2006
Posts: 2,087
|
Or...
12-16-2006 06:19
Another option that requires substantially less code, and does not have the delay implications of the dataserver() event, is to use llMessageLinked() .. pretty much straight out of the example scripts on the wiki. Benefits: Much faster than notecard based settings, less code to clutter up your scripts Risks: Because the "config" is indeed code, more chance that an inexperienced user might muck things up. Strong documentation is the order of the day. Configuration Script looks like this: // llMessageLinked based config // Name/Value pairs - These are passed on to the main // application script when requested // Based on wiki example at // http://www.lslwiki.com/lslwiki/wakka.php?wakka=ExampleArgumentMultiplexing
// Begin User Settings integer sRange = 14; float sArc = PI; integer sRate = 2; // End of User Settings. // Do not change the following under penalty of loss of genetals
default { link_message(integer sender_num, integer num, string request, key id) { // Send back requested values if (request == "send_params") { list params = ["params", sRange, sArc, sRate]; llMessageLinked(LINK_THIS, 0, llDumpList2String(params,"-=-"), NULL_KEY); } } }
And the application script: // Application script - adapt to call in parameters from // config script as needed. touch_start is used here for // example only, obviously there's a better trigger // such as state_entry() inside your 'configure' state. // // Based on wiki example at // http://www.lslwiki.com/lslwiki/wakka.php?wakka=ExampleArgumentMultiplexing
integer sRange; float sArc; integer sRate;
default { touch_start(integer total_number) { llMessageLinked(LINK_THIS, 0, "send_params", NULL_KEY); } link_message(integer sender_num, integer num, string message, key id) { list args = llParseStringKeepNulls( message, ["-=-"], [] ); string response = llList2String( args, 0); if (response == "params") { sRange = (integer)llList2String( args, 1); sArc = (float)llList2String( args, 2); sRate = (integer)llList2String( args, 3); } } }
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
12-16-2006 11:38
And the most obvious drawe back is that you need to edit it and recompile to update your object rather than just dropping in a new notecard.
|
|
Zaphod Kotobide
zOMGWTFPME!
Join date: 19 Oct 2006
Posts: 2,087
|
12-16-2006 12:47
Yup.. there's that too. Neither is necessarily ideal. Ideal would be the ability to directly convert strings to variables and functions.
I noticed you're checking string length on the incoming data and basically determining that it isn't a blank line by testing string length for >3 - Am I correct in assuming that there is actually no solid way to do this? No regex pattern matching?
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
12-16-2006 12:57
From: Zaphod Kotobide Yup.. there's that too. Neither is necessarily ideal. Ideal would be the ability to directly convert strings to variables and functions.
I noticed you're checking string length on the incoming data and basically determining that it isn't a blank line by testing string length for >3 - Am I correct in assuming that there is actually no solid way to do this? No regex pattern matching? None taht I am aware off, not that that means much!
|
|
Shippley Dittmann
Registered User
Join date: 30 Aug 2006
Posts: 13
|
reagarding the notecard configuration
06-28-2007 19:20
I am trying to learn the basic principals of the notecard configuration feature. I kind of get the idea from the script....
Can I see what an example Notecard text would be to change the settings for this script?
Something to do with playing a sound..??
Maybe a little explanation.
/shrug
|
|
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
|
06-29-2007 00:14
From: Shippley Dittmann I am trying to learn the basic principals of the notecard configuration feature. I kind of get the idea from the script....
Can I see what an example Notecard text would be to change the settings for this script?
Something to do with playing a sound..??
Maybe a little explanation.
/shrug The exact content of a notecard is completely up to you, all the datatserver does is return a line of text. I usually use key=value pairs for mosty things as its nice and simple. i.e. SOUND=mysoundfile Script Fragment dataserver(key queryid, string data) { //Check to make sure this is the request we are making. //Remember that when data comes back from the dataserver, //it goes to *all* scripts in your prim. //So you have to make sure this is the data you want, and //not data coming from some other script. if (dataRequestID == queryid) { // llOwnerSay("received " + data); llSetTimerEvent(0); //If we haven't reached the end of the file if (data != EOF) { // ; used as a comment line if(llGetSubString(data, 0,0) != ";") { // Lines are in the form KEYWORD=value=extra list ldata = llParseString2List(data,["="],[""]); string command = llList2String(ldata,0); string parameter1 = llList2String(ldata,1); string parameter2 = llList2String(ldata,2); // Process commands here } //Request next line ++lineCounter; dataRequestID = llGetNotecardLine(notecardName, lineCounter); llSetTimerEvent(10); } else { state RunMode; } } }
_____________________
I'm back......
|
|
Domino Marama
Domino Designs
Join date: 22 Sep 2006
Posts: 1,126
|
06-29-2007 02:00
Here's an example of the way I do it. Obviously similar to the others but uses a notecard with "item name=item data" on each line. It also supports multiple data items per config item ("item name = item data, more data, even more data" Comments can be included in the config by starting the line with # and it handles the most common cases of where people put unexpected spaces automatically. In this example I've set it up for an optional _config notecard such as: # System Channel is the main communications channel, it should be unique System Channel = -55555 # Add a list of sims to use here Sim List = Spinolds Flat, Mooz,URBIS # set x y and z for the offset Offset = 1.0, 10.0, 5.0 # another way to do lists Nickname = Dom, Domino Marama Nickname = DJ, Diamond Jubilee integer systemChannel = -67894; list simList = [ "Spinolds Flat" ]; list avatarNames; list avatarNicknames; vector offset; integer tI; list tL; string tS; key request;
default { state_entry() { if ( llGetInventoryType( "_config" ) == INVENTORY_NOTECARD ) { request = llGetNotecardLine( "_config", tI = 0 ); } else { state ready; } }
dataserver(key query, string data) { if ( request == query ) { if ( data == EOF ) { state ready; } else { if ( llGetSubString( data, 0 ,0 ) != "#" && llStringTrim(data, STRING_TRIM) != "") { tL = llParseString2List( data, ["= ", "=", " , ", ", ", " ,", ","],[] ); tS = llToLower( llStringTrim( llList2String( tL, 0 ), STRING_TRIM )); // at this point tS contains lower case item name and tL[1,-1] contains data if ( tS == "system channel" ) { systemChannel = llList2Integer( tL, 1); } else if ( tS == "sim list" ) { simList = llList2List( tL, 1, -1 ); } else if ( tS == "offset" ) { offset = < llList2Float( tL, 1 ), llList2Float( tL, 2 ), llList2Float( tL, 3 ) >; } else if ( tS == "nickname" ) { // funky way of doing avatarNames += llList2List( tL,2,2 ); is to save memory avatarNames = ( avatarNames = [] ) + avatarNames + llList2List( tL,2,2 ); avatarNicknames = ( avatarNicknames = [] ) + avatarNicknames + llList2List( tL,1,1 ); } } request = llGetNotecardLine( "_config", ++tI ); } } } }
state ready { state_entry() { llOwnerSay( "good to go on channel " + (string)systemChannel + " for " + llDumpList2String( simList, ", " ) ); } }
|