Difference between revisions of "Talk:Second Life Railroad/SLRR Switch"
(One intermediate revision by the same user not shown) | |||
Line 67: | Line 67: | ||
:'''0''' channel for local control | :'''0''' channel for local control | ||
====A script | ====A Demo script for this specification==== | ||
// =================================================================================== | |||
// Example script to show correct reading of the description string of SLRR switchstands | |||
// | |||
// Executive sumary | |||
// The key routine in this example is the function GetDescriptionSubfield | |||
// This routine accepts a description string, and indices for field en subfield to read. | |||
// The data at the indicated position in the description is returned. | |||
// | |||
// Demo script function | |||
// Touching the prim that contains this script will tell the owner the ID of the detected | |||
// switches, the destinations (given the current status) and the chat channel. | |||
// The utility function ReadSwitchDescription provides an easy way to extract any of the subfields | |||
// in a way that will not break when private switches are encountered that have additional info | |||
// in the description (sub)field. | |||
// This example is in the public domain and can be used freely | |||
// =================================================================================== | |||
// | |||
// Remarks: | |||
// A good case can be made for re-wording the standard in such a way to it is NOT | |||
// alllowed anymore to add new subfields in exisiting parts, but ONLY fields and subfields | |||
// at the end of the string. | |||
// That would simplify the decoding, but yield a slightly less logical description. | |||
// | |||
// | |||
// BEWARE! The description field is limited to 127 bytes, this might not be obvious until | |||
// the prim is stored in inventory and re-rezzed. | |||
// =================================================================================== | |||
// Constants to be used to retrieve fields and subfields of the description string | // Constants to be used to retrieve fields and subfields of the description string | ||
// of SLRR standard switches. Currently 6 fields are defined, delimited by "~" | // of SLRR standard switches. Currently 6 fields are defined, delimited by "~" | ||
string NAME_SWITCH = "Switch Stand"; | |||
integer SLRR_SWITCH_DESC_ID = 0; // unique identifier of the switch | integer SLRR_SWITCH_DESC_ID = 0; // unique identifier of the switch | ||
Line 85: | Line 116: | ||
integer ADDRESS_Z = 3; // z coordinate of switch root prim | integer ADDRESS_Z = 3; // z coordinate of switch root prim | ||
// Within the | // Within the STATUS field at least the following part is expected | ||
integer STATUS | // Future extensions will be delimeted by "." | ||
integer STATUS = 0; // Text string of status | |||
// Currently only the following values for STATUS have been defined | |||
string NAME_MAIN = "Main"; | |||
string NAME_BRANCH = "Branch"; | |||
//Witin the connection descriptions (HEADING, MAIN and BRANCH) at least the following | |||
/ part is expected. Future extensions will be delimeted by "." | |||
integer CONNECTION_DESTINATION = 0; // Informal description of direction for this connection | |||
//Witin the CHANNEL description field at least the following parts are expected, delimeted by "." | |||
integer LOCAL_CHANNEL = 0; // channel for local control of the switch | |||
// =================================================================================== | |||
// Function GetDescriptionSubfield. Read one subfield of the switchstand description | |||
// Returns a string with the requested subfield. Note that for fields that contains only a | |||
// single item field and subfield are equivalent. | |||
// ==================================================================================== | |||
string GetDescriptionSubfield(string sDescription, integer iField, integer iSubField) | |||
{ | |||
// Compact one line version | |||
return(llList2String(llParseString2List(llList2String(llParseString2List(sDescription, ["~"],[]), iField), ["."],[]), iSubField)); | |||
// Here is how this function is composed: | |||
// list lFields = llParseString2List(sDescription, ["~"],[]); // get the main fields | |||
// string sOneField = llList2String(lFields, iField); // pick the one we need | |||
// list lSubfields = llParseString2List(sOneField, ["."],[]); // Get the subfields | |||
// string sOneSubfield = llList2String(lSubfields, iSubField); // Pick the one we need | |||
// return(sOneSubfield); | |||
} | |||
// | // =================================================================================== | ||
string | // *** Main program *** | ||
// We use the example script for the sensor event on the wikki as the basis of this demo | |||
// Note that there are in principle more efficient ways to get the description string | |||
// of the prim than a sensor (using messaging between swtiches). These methods are | |||
// currently under development by the VRC | |||
// =================================================================================== | |||
// | // Sensor variables | ||
float g_fRange; // in meters | |||
float g_fArc; // in radial | |||
float g_fSphere; // in radial | |||
// | |||
// | default | ||
{ | |||
//integer | state_entry() | ||
{ | |||
g_fSphere = PI; // look all around, not used in this demo | |||
g_fArc = PI/4; // look forward, make cone as narrow as practical | |||
g_fRange = 10; // 10 meter, dont scan more than you need | |||
} | |||
touch_start(integer numberDetected) | |||
{ | |||
// We look for the switch stand (an active object) | |||
llSensor(NAME_SWITCH, "", ACTIVE, g_fRange, g_fArc); | |||
} | |||
sensor (integer numberDetected) | |||
{ | |||
// Note: in this example all variables are explicitly named and stored, in a real application | |||
// this could be done more compact ( see for an example the code of GetDescriptionSubfield() | |||
// For clarity we expand the string handling here. | |||
string sDescription; | |||
string sStatus; | |||
string sRegion; | |||
string sX; | |||
string sY; | |||
string sZ; | |||
string sDestination; | |||
string sChannel; | |||
//prepare the response string, we start with a new line | |||
string msg = "\n"; | |||
integer i = -1; | |||
while(numberDetected > ++i) //loop trough all detected items | |||
{ | |||
//First get the full description string of the detected switch | |||
sDescription = (string)llGetObjectDetails( llDetectedKey(i), [OBJECT_DESC]); | |||
// We extract the Region of this switch, the unique identifier x.y.z and the local channel number | |||
// Note that it would be more convenient to have the location vector coordinates delimited by "," | |||
// like in a standard vector. This would allow easier | |||
// retrieval of the whole vector <x.y.z> | |||
sRegion = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_ID, ADDRESS_REGION); | |||
sX = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_ID, ADDRESS_X); | |||
sY = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_ID, ADDRESS_Y); | |||
sZ = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_ID, ADDRESS_Z); | |||
sChannel = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_CHANNEL, LOCAL_CHANNEL); | |||
//Look at the current status using the GetDescriptionSubfield function | |||
sStatus = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_STATUS, STATUS); | |||
// Get the destination for the current setting | |||
if (sStatus == NAME_MAIN) | |||
{ | |||
sDestination=GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_MAIN, CONNECTION_DESTINATION); | |||
} | |||
else if(sStatus == NAME_BRANCH) | |||
{ | |||
sDestination=GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_BRANCH, CONNECTION_DESTINATION); | |||
} | |||
else | |||
{ | |||
sDestination = "destination unknown (due to invalid status)"; | |||
} | |||
msg += sRegion + " " + sX+ "," + sY + " using channel " + sChannel + " " + "is currently set for " + sDestination + "\n"; | |||
} | |||
llWhisper(0, msg); | |||
} | |||
no_sensor() | |||
{ | |||
llOwnerSay("No switch within viewing range"); | |||
} | |||
} | |||
Note that none of this is mandatory for a scripter. If sombody want to write quick and dirty code that works now, that is fine. However, the point is that such a script can not be expected to keep working in the future. Scripts using the techique outlined in the above example are guaranteed to work, even if additional info is added to the description string. | |||
This priciple is more general than the switch standard example, and for ''all'' description strings a script should retrieve the info using indexes rather than asuming that no additonal info will ever be present. | |||
This priciple is more general than the switch standard, and for ''all'' description strings a script should retrieve the info using indexes rather than asuming that no additonal info will ever be present. | |||
[[User:Vaughn Deluca|Vaughn Deluca]] 00:45, 6 January 2011 (UTC) | [[User:Vaughn Deluca|Vaughn Deluca]] 00:45, 6 January 2011 (UTC) |
Latest revision as of 01:29, 8 January 2011
On this page you can voice your comments and your own idea about the SLRR Switch concept
--Stryker J 21:15, 28 December 2009 (UTC)
CORRECTION: While desirable, the ability to switch from one track to another on the SLRR is NOT essential. Our locomotives are made of 0s and 1s, not 100 tons of iron, they can be easily moved from one track to another. Also, switches such as the one described here have been available from private SL residents for years. Jer Straaf
CORRECTION TO THE CORRECTION
>>...While desirable, the ability to switch from one track to another on the SLRR is NOT essential...<<
You're right. it isn't essential, but tedious to move the trains by editing them. It is killing a lot of the experience Everest Piek 21:36, 29 August 2010 (UTC)
problem about being noob proof
In RL, the switches are signalled as they are built, means, there are always a straight track and a branching track. the arrow is always showing to the branching track, thats not necessarily a branching Line. For that, having the signals once this way, once the other way, might be confusing to noobs. I would plead for having them in a universal way set as the switches are built, as they are signalled in RL. Everest Piek 21:43, 29 August 2010 (UTC)
- There is a little bit of education to be done. I agree with the principle of making sure the switches are all setup the same way. In order to make the switches more Noob friendly the dwarflights are also installed. --Stryker J 09:32, 30 August 2010 (UTC)
- Thanks Guys. I will redact my statment under the Signal diagram and build tham as Everest advises. Sylvan
An exact specification of the way the description string in the switch stand should be read is needed.
Example problem: A train script might get the switch channel by reading the item in the string at index 5. This is OK. However, another train script reads the last field of the description string to get the channel. This would also work, and is within the current specification.
While both scripts follow the standard, the last script limits compatibility. An advanced switch script, may for instance have a ~ and a private channel added at the end of the description string. The first train script would work, and the last train script would get the wrong channel and break with this advances switch script. To maintain maximal freedom for experimentation without risk of breaking existing scripts, the standard needs to be specific about the posibility that extra information might be present in the string.
The key point is that the standard for the description string currently specifies the minimal info that a script can expect. For maximal flexibility it should be clear that in the future in each field information might be added. Therfore, indexes should be use to read the data from the description (See example script below)
Proposed text to be put up in the page:
Currently 6 fields are defined, delimited by "~" Their indexes are:
- 0 unique identifier of the switch
- 1 current status of the switch
- 2 heading connection-info
- 3 main connection-info
- 4 branch connection-info
- 5 channel for local control of the switch
Indexes and descriptions for the subfields within these fields:
- - Within the identifier of the switch, at least the following parts are expected, delimited by "."
- 0 region name
- 1 x coordinate of switch root prim
- 2 y coordinate of switch root prim
- 3 z coordinate of switch root prim
- Within the status field at least the following part is expected, future extensions will be delimeted by "."
- 0 text string describing switch status
- Currently the only defined values for this part are "Main" and "Branch"
- Within each connection-info fields (heading, main and branch fields) at least the following parts are expected, delimeted by "."
- 0 Informal destination description string
Within the channel field at least the following part is expected, future extensions will be delimeted by "."
- 0 channel for local control
A Demo script for this specification
// =================================================================================== // Example script to show correct reading of the description string of SLRR switchstands // // Executive sumary // The key routine in this example is the function GetDescriptionSubfield // This routine accepts a description string, and indices for field en subfield to read. // The data at the indicated position in the description is returned. // // Demo script function // Touching the prim that contains this script will tell the owner the ID of the detected // switches, the destinations (given the current status) and the chat channel. // The utility function ReadSwitchDescription provides an easy way to extract any of the subfields // in a way that will not break when private switches are encountered that have additional info // in the description (sub)field. // This example is in the public domain and can be used freely // =================================================================================== // // Remarks: // A good case can be made for re-wording the standard in such a way to it is NOT // alllowed anymore to add new subfields in exisiting parts, but ONLY fields and subfields // at the end of the string. // That would simplify the decoding, but yield a slightly less logical description. // // // BEWARE! The description field is limited to 127 bytes, this might not be obvious until // the prim is stored in inventory and re-rezzed. // =================================================================================== // Constants to be used to retrieve fields and subfields of the description string // of SLRR standard switches. Currently 6 fields are defined, delimited by "~" string NAME_SWITCH = "Switch Stand"; integer SLRR_SWITCH_DESC_ID = 0; // unique identifier of the switch integer SLRR_SWITCH_DESC_STATUS = 1; // current status of the switch integer SLRR_SWITCH_DESC_HEADING = 2; // heading connection info integer SLRR_SWITCH_DESC_MAIN = 3; // main connection info integer SLRR_SWITCH_DESC_BRANCH = 4; // branch connection info integer SLRR_SWITCH_DESC_CHANNEL = 5; // channel for local control of the switch //Within the ID field at least the following parts are expected, delimeted by "." integer ADDRESS_REGION = 0; // region name integer ADDRESS_X = 1; // x coordinate of switch root prim integer ADDRESS_Y = 2; // y coordinate of switch root prim integer ADDRESS_Z = 3; // z coordinate of switch root prim // Within the STATUS field at least the following part is expected // Future extensions will be delimeted by "." integer STATUS = 0; // Text string of status // Currently only the following values for STATUS have been defined string NAME_MAIN = "Main"; string NAME_BRANCH = "Branch"; //Witin the connection descriptions (HEADING, MAIN and BRANCH) at least the following / part is expected. Future extensions will be delimeted by "." integer CONNECTION_DESTINATION = 0; // Informal description of direction for this connection //Witin the CHANNEL description field at least the following parts are expected, delimeted by "." integer LOCAL_CHANNEL = 0; // channel for local control of the switch // =================================================================================== // Function GetDescriptionSubfield. Read one subfield of the switchstand description // Returns a string with the requested subfield. Note that for fields that contains only a // single item field and subfield are equivalent. // ==================================================================================== string GetDescriptionSubfield(string sDescription, integer iField, integer iSubField) { // Compact one line version return(llList2String(llParseString2List(llList2String(llParseString2List(sDescription, ["~"],[]), iField), ["."],[]), iSubField)); // Here is how this function is composed: // list lFields = llParseString2List(sDescription, ["~"],[]); // get the main fields // string sOneField = llList2String(lFields, iField); // pick the one we need // list lSubfields = llParseString2List(sOneField, ["."],[]); // Get the subfields // string sOneSubfield = llList2String(lSubfields, iSubField); // Pick the one we need // return(sOneSubfield); } // =================================================================================== // *** Main program *** // We use the example script for the sensor event on the wikki as the basis of this demo // Note that there are in principle more efficient ways to get the description string // of the prim than a sensor (using messaging between swtiches). These methods are // currently under development by the VRC // =================================================================================== // Sensor variables float g_fRange; // in meters float g_fArc; // in radial float g_fSphere; // in radial default { state_entry() { g_fSphere = PI; // look all around, not used in this demo g_fArc = PI/4; // look forward, make cone as narrow as practical g_fRange = 10; // 10 meter, dont scan more than you need } touch_start(integer numberDetected) { // We look for the switch stand (an active object) llSensor(NAME_SWITCH, "", ACTIVE, g_fRange, g_fArc); } sensor (integer numberDetected) { // Note: in this example all variables are explicitly named and stored, in a real application // this could be done more compact ( see for an example the code of GetDescriptionSubfield() // For clarity we expand the string handling here. string sDescription; string sStatus; string sRegion; string sX; string sY; string sZ; string sDestination; string sChannel; //prepare the response string, we start with a new line string msg = "\n"; integer i = -1; while(numberDetected > ++i) //loop trough all detected items { //First get the full description string of the detected switch sDescription = (string)llGetObjectDetails( llDetectedKey(i), [OBJECT_DESC]); // We extract the Region of this switch, the unique identifier x.y.z and the local channel number // Note that it would be more convenient to have the location vector coordinates delimited by "," // like in a standard vector. This would allow easier // retrieval of the whole vector <x.y.z> sRegion = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_ID, ADDRESS_REGION); sX = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_ID, ADDRESS_X); sY = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_ID, ADDRESS_Y); sZ = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_ID, ADDRESS_Z); sChannel = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_CHANNEL, LOCAL_CHANNEL); //Look at the current status using the GetDescriptionSubfield function sStatus = GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_STATUS, STATUS); // Get the destination for the current setting if (sStatus == NAME_MAIN) { sDestination=GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_MAIN, CONNECTION_DESTINATION); } else if(sStatus == NAME_BRANCH) { sDestination=GetDescriptionSubfield(sDescription, SLRR_SWITCH_DESC_BRANCH, CONNECTION_DESTINATION); } else { sDestination = "destination unknown (due to invalid status)"; } msg += sRegion + " " + sX+ "," + sY + " using channel " + sChannel + " " + "is currently set for " + sDestination + "\n"; } llWhisper(0, msg); } no_sensor() { llOwnerSay("No switch within viewing range"); } }
Note that none of this is mandatory for a scripter. If sombody want to write quick and dirty code that works now, that is fine. However, the point is that such a script can not be expected to keep working in the future. Scripts using the techique outlined in the above example are guaranteed to work, even if additional info is added to the description string.
This priciple is more general than the switch standard example, and for all description strings a script should retrieve the info using indexes rather than asuming that no additonal info will ever be present.
Vaughn Deluca 00:45, 6 January 2011 (UTC)