Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Lists Changing Order?

Shifting Dreamscape
Always questioning ...
Join date: 12 Dec 2007
Posts: 266
04-18-2008 23:58
Is there any know issue with SL reordering list variables in scripts? Let me explain...

I have the following code that loads a set of variables (this is actually a trimmed down version to avoid the complications of the rest of the script. The basic idea is that i need to group a series of prims (windows) to be later able to set their values when the user decides to. Each group (room) can have a number of windows in it, each with their own set of values:

<php>
...

//The window will call passing a long data string in message
//These are the values associated with the window seperated by a @

//Pare out the data
dataList = llParseString2List(message, ["@"],[""]);

//Find the next position in the datasets .. this just sees how many
//elements there are in the linknum list as there is one for each room
newIndex = llGetListLength(gWindowLinkNum);

//Get the room name from the list
windowName = llList2String(dataList,0);

//Check if room name already in List
index = llListFindList(gWindowOptions, [windowName]);
if ( index != -1)
{
//Already in the list so we add to the variable there the next available index
//number .. this will point to the position in the lists for the window stored values
linkList = llList2String(gListPosit, index) + "@" + (string)newIndex;
gListPosit = llListReplaceList(gListPosit, [linkList], index, index);
}
else
{
//Create new entry in the base lists
gWindowOptions = gWindowOptions + [windowName];
gListPosit = gListPosit + [(string)newIndex];
}

//Then Store the Data .. the index of each of the following values should be the same ...
//it means that we can then recuperate the index values for a particular room
gWindowLinkNum = (gWindowLinkNum=[]) + gWindowLinkNum + [(string)linkId];
gInFace = (gInFace=[]) + gInFace + [inFace];
gInColor = (gInColor=[]) + gInColor + [(vector)llList2String(dataList,2)];
gInText = (gInText=[]) + gInText + llList2List(dataList, 3, 3);

...
</php>

Then the basic code used to retrieve the data is as follows:

<php>
...
integer quit = 0;
integer listLen = llGetListLength(gListPosit);

//Now call the windows
while (quit == 0 && i < listLen)
{
//For each element in the list of rooms ... check to see if this is the same as the one selected from the
//Dialog ... or we are doing all
if (llList2String(gWindowOptions, i) == gWinSelected || gWinSelected == "All";)
{

//Need to Split out the List Positions Ids .. the indexs of windows associated with
//this room
indexList = llParseString2List(llList2String(gListPosit, i),["@"],[""]);
indexLen = llGetListLength(indexList);

//Now for each window associated with the room
for (x = 0; x < indexLen; x++)
{
//get the index in the data lists associated
index = llList2Integer(indexList, x);

//get the pertinent values .. link of the window first
linkNum = llList2Integer(gWindowLinkNum, index);
llSetLinkTexture(linkNum, llList2String(gInText, index), faceWork)

...
</php>

So .. if you have hung on this long I am sure you are asking when I'll get to the problem. Well after finally getting the earlier kinks worked out I had this installed and configured and working, each window across the three rooms was getting its proper texture. I then went away for about an hour or so and came back later with a friend to show them the house, and suddenly the textures being set were off. And it wasn't that just the rooms were being mixed up, it was that the windows were being crossed across rooms, i.e. if when setup, Room A contained windows 1-4 and Room B Windows 5-8, now when selecting to set room C, windows 1,5,6,7 were being set. So it appears that some of the lists have been reordered.

Is this a known issue in SL? Is there a work around?

Thanks!
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
04-19-2008 05:36
The code you have looks good on the face which makes me think you are corrupting the data elsewhere.

You may want to consider using pipe "|" as your separator since it can't appear in asset names.
_____________________
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
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
04-19-2008 06:55
Haven't heard of any problems and I use some really heavy multiple lists manipulations in my teleport hud with no problems.

Click on the link in my sig and take a look at the teleport hud script. You will see that I used strides which might come in handy for what you are doing. This would allow for a master list like so:

CODE

list main = ["roomA","window1","roomB","window3","roomA","window2","roomC","window6",
"roomB","window8","roomA","window4","roomD","window7","roomB","window5"];

default
{
touch_start(integer total_number)
{
main = llListSort(main,2,1);
integer start = llListFindList(main,["roomB"]);
integer end = llListFindList(main,["roomC"]);
list room = llList2List(main,start,end - 1);
list windows = llList2ListStrided(main,start,end - 1,2);
llOwnerSay(llDumpList2String(room, ","));
llOwnerSay(llDumpList2String(windows, ","));

}
}

returns this output:
"temp2: roomB,window8,roomB,window3,roomB,window5
temp2: window8,window3,window5"

If I completely missed it in this answer then you could post the whole code and we will give it a look and help spot the problem.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Shifting Dreamscape
Always questioning ...
Join date: 12 Dec 2007
Posts: 266
04-19-2008 07:17
Strife - I thought at first that I could be corrupting but once the lists are set up during the configuration process they do not get modified again. And as I said at one point they were correct.

Jesse - I'll take a look at the script. Thouhgt about using stride .. but my lists ae created dynamically and could get longer than the max allowed.
Shifting Dreamscape
Always questioning ...
Join date: 12 Dec 2007
Posts: 266
04-19-2008 07:17
Here is the whole origianl code ...

//
CODE

// Window Tint Controller Script (put into controller prim)
//
// *******************************************************************
// This program is free software; you can redistribute it and/or
// modify as you wish. Just don't try and sell it to someone ...
// that would not be nice or fair.
// If you have paid someone for this script .. contact me and we'll
// track them down inworld and harass them ;-)
//
// While I do not offer support for this script if you have questions
// feel free to contact me inworld.
//
// Writen by Shifting Dreamscape
// *******************************************************************

//Parameter Notecard
string DATA_NOTECARD = "control_data_params";
//Notecard read
integer gLine;
key gParamData;

//Values from Param Notecard
//Dialog Channel to listen on
integer DIALOG_CHAN;//dialog_channel
//Chat Channel To Listen to
integer RESET_CHAN;//windowcontrol_chat_channel
//Channel the window scripts listen on
integer WINDOW_SET_CHAN;//window_comm_channel
//DataLink 'channel'
integer DATA_CHAN;//window_data_channel
//Link channels 'listened' to
integer INDIVID_CHAN;//window_individ
integer GROUP_CHAN;//window_group
//ID of the controller
string CTRL_ID;
//End Parameter Variables

//The % to Tint the window
list TINT_OPTIONS = ["40%", "20%", "None", "100%", "80%", "60%"];
//Side of the Window to Tint
list SIDE_OPTIONS = ["Outside", "Inside", "Both"];


//Identifiers for the different dialog boxes
integer NO_DIALOG = 0;
integer CHECK_WINDOW = 1;
integer CHECK_TINT = 2;
integer CHECK_SIDE = 3;

//Variable set when a window is chosen
string gWinSelected;
//Holds the Tint level Chosen
float gMsgTint;
//Holds the side of the window to tint
string gSideModifier;
//Holds which Dialog was last shown
integer gCurDialog;

//List of Window names
list gWindowOptions;

//Holds the index positions for a winodw or window group
list gListPosit;

//Data Lists
list gWindowLinkNum;
list gInFace;
list gInColor;
list gInText;
list gIn100Color;
list gIn100Text;
list gOutFace;
list gOutColor;
list gOutText;
list gOut100Color;
list gOut100Text;

//Temporary Data lists
list gTempWindowOptions;
list gTempListPosit;
list gTempWindowLinkNum;
list gTempInFace;
list gTempInColor;
list gTempInText;
list gTempIn100Color;
list gTempIn100Text;
list gTempOutFace;
list gTempOutColor;
list gTempOutText;
list gTempOut100Color;
list gTempOut100Text;

//Listener Handle
integer gListenHandle;

//Functions
integer call_windows()
{
integer i = 0;
integer x = 0;
integer quit = 0;
integer listLen = llGetListLength(gListPosit);
list indexList;
integer indexLen;
integer index;
integer linkNum;
integer faceWork;
string sText;
string message;

//Now call the windows
while (quit == 0 && i < listLen)
{
if (llList2String(gWindowOptions, i) == gWinSelected || gWinSelected == "All")
{

//Need to Split out the List Positions Ids
indexList = llParseString2List(llList2String(gListPosit, i),["@"],[""]);
indexLen = llGetListLength(indexList);

for (x = 0; x < indexLen; x++)
{
index = llList2Integer(indexList, x);
linkNum = llList2Integer(gWindowLinkNum, index);

//Check for a negative Link ID .. this means that it is an unlinked window
if (linkNum < 0)
{
//Send ... WinControlID, SideMod, Tint .. The window has stored its texture/color values
message = CTRL_ID + "@" + gSideModifier + "@" + (string)gMsgTint;
llRegionSay(linkNum, message);
}
else
{

//Check for each side
if (gSideModifier != "Inside")
{
faceWork = llList2Integer(gOutFace, index);

//Now depending on the Tint % we set one color or other
if (gMsgTint == 1)
{
//Only do this if we really have a texture ... a none will be here if not
sText = llList2String(gOut100Text, index);
if (sText != "non")
{
llSetLinkColor(linkNum, llList2Vector(gOut100Color, index), faceWork);
llSetLinkTexture(linkNum, llList2String(gOut100Text, index), faceWork);
}
}
else
{
llSetLinkColor(linkNum, llList2Vector(gOutColor, index), faceWork);
llSetLinkTexture(linkNum, llList2String(gOutText, index), faceWork);
}
llSetLinkAlpha(linkNum, gMsgTint, faceWork);
}
if (gSideModifier != "Outside")
{
faceWork = llList2Integer(gInFace, index);

//Now depending on the Tint % we set one color or other
if (gMsgTint == 1)
{
//Only do this if we really have a texture ... a none will be here if not
sText = llList2String(gOut100Text, index);
if (sText != "non")
{
llSetLinkColor(linkNum, llList2Vector(gOut100Color, index), faceWork);
llSetLinkTexture(linkNum, llList2String(gOut100Text, index), faceWork);
}
}
else
{
llSetLinkColor(linkNum, llList2Vector(gInColor, index), faceWork);
llSetLinkTexture(linkNum, llList2String(gInText, index), faceWork);
}
llSetLinkAlpha(linkNum, gMsgTint, faceWork);
}
}
}
if (gWinSelected != "All")
{
quit = 1;
}
}
i++;
}
return 0;
}//End call_windows



//Body
default
{
state_entry()
{
//Initialize Window Options to null
gWindowOptions = ["Set"];
//Read in from the notecard my data
gLine = 0;
gParamData = llGetNotecardLine(DATA_NOTECARD, gLine);
} // end state_entry()

dataserver(key requested, string data)
{
list dataPair;
string dataKey;
string dataValue;

if (requested == gParamData && data != EOF)
{
if (llGetSubString(data, 0, 1) != "//" && data != "")
{
dataPair = llParseString2List(data, ["="], [""]);
dataKey = llList2String(dataPair, 0);
dataValue = llList2String(dataPair, 1);

if (dataKey == "dialog_channel")
{
DIALOG_CHAN = (integer)dataValue;
}
else if (dataKey == "windowcontrol_chat_channel")
{
RESET_CHAN = (integer)dataValue;
}
else if (dataKey == "window_comm_channel")
{
WINDOW_SET_CHAN = (integer)dataValue;
}
else if (dataKey == "window_data_channel")
{
DATA_CHAN = (integer)dataValue;
}
else if (dataKey == "window_individ")
{
INDIVID_CHAN = (integer)dataValue;
}
else if (dataKey == "window_group")
{
GROUP_CHAN = (integer)dataValue;
}
else if (dataKey == "window_control_id")
{
CTRL_ID = dataValue;
}
}
++gLine;
gParamData = llGetNotecardLine(DATA_NOTECARD, gLine);
}
}//End dataserver


link_message(integer sender_number, integer channel, string message, key id)
{
list dataList;
integer index;
integer newIndex;
integer linkId;
integer inFace;
string linkList;
string tint;
string windowName;

if (channel == INDIVID_CHAN)
{
llDialog(id, "Which window would you like to tint?", gWindowOptions, DIALOG_CHAN);

//Start Listening
gListenHandle = llListen(DIALOG_CHAN, "", NULL_KEY, "");

//Set Timer to Turn off this channel in case the user does nto go all the way through
llSetTimerEvent(60.0);

//Flag for what dialog is visible
gCurDialog = CHECK_WINDOW;
}
else if (channel == GROUP_CHAN)
{
gWinSelected = "All";
dataList = llParseString2List(message, ["@"], [""]);

//Change the tint value to a number
if (llList2String(dataList, 0) == "None")
{
gMsgTint = 0;
}
else
{
tint = llList2String(dataList, 0);
gMsgTint = (float)llGetSubString(tint, 0, llStringLength(tint)-2)/100;
}
gSideModifier = llList2String(dataList, 1);
call_windows();
}
else if (channel == DATA_CHAN)
{
//The window will call passing a long data string in message
//The structure is name, inside face, color, texture, the the outside values
//each value seperated by the @ symbol
//All the data will be just appended to the end of the various lists
//The new list position will be added to a @ seperated string that holds
//the same position in its list as the window name

dataList = llParseString2List(message, ["@"],[""]);

//Next Position in the data sets
newIndex = llGetListLength(gTempWindowLinkNum);
windowName = llList2String(dataList,0);

//Check if window name already in List
index = llListFindList(gTempWindowOptions, [windowName]);
if ( index != -1)
{
linkList = llList2String(gTempListPosit, index) + "@" + (string)newIndex;
gTempListPosit = llListReplaceList(gTempListPosit, [linkList], index, index);
}
else
{
//Create new entry
gTempWindowOptions = gTempWindowOptions + [windowName];
gTempListPosit = gTempListPosit + [(string)newIndex];
}

//Then Store the Data
//First check the inface value .. if negative we are working with an unlinked window
//and the value in inface needs to be used for linknum
inFace = llList2Integer(dataList, 1);
if (inFace < 0)
{
linkId = inFace;
}
else
{
linkId = sender_number;
}
gTempWindowLinkNum = (gTempWindowLinkNum=[]) + gTempWindowLinkNum + [(string)linkId];
gTempInFace = (gTempInFace=[]) + gTempInFace + [inFace];
gTempInColor = (gTempInColor=[]) + gTempInColor + [(vector)llList2String(dataList,2)];
gTempInText = (gTempInText=[]) + gTempInText + llList2List(dataList, 3, 3);
gTempIn100Color = (gTempIn100Color=[]) + gTempIn100Color + [(vector)llList2String(dataList,4)];
gTempIn100Text = (gTempIn100Text=[]) + gTempIn100Text + llList2List(dataList, 5, 5);
gTempOutFace = (gTempOutFace=[]) + gTempOutFace + llList2List(dataList, 6, 6);
gTempOutColor = (gTempOutColor=[]) + gTempOutColor + [(vector)llList2String(dataList,7)];
gTempOutText = (gTempOutText=[]) + gTempOutText + llList2List(dataList, 8, 8);
gTempOut100Color = (gTempOut100Color=[]) + gTempOut100Color + [(vector)llList2String(dataList,9)];
gTempOut100Text = (gTempOut100Text=[]) + gTempOut100Text + llList2List(dataList, 10, 10);

}
}//End link_message

listen(integer channel, string name, key id, string message)
{
//Which Channel??
if (channel == RESET_CHAN)
{
if (message == "Done")
{
llSetTimerEvent(0.0);

//we close out the list with all and reset
gTempWindowOptions = gTempWindowOptions + ["All", "Reset"];
llListenRemove(gListenHandle);
llSay(0, "To remove the scripts from the windows simply say 'Die' on channel " + (string)WINDOW_SET_CHAN);
llMessageLinked(LINK_ALL_OTHERS, 0, "Done", NULL_KEY);

//Finally update the storage variables
gWindowOptions = gTempWindowOptions;
gListPosit = gTempListPosit;
gWindowLinkNum = gTempWindowLinkNum;
gInFace = gTempInFace;
gInColor = gTempInColor;
gInText = gTempInText;
gIn100Color = gTempIn100Color;
gIn100Text = gTempIn100Text;
gOutFace = gTempOutFace;
gOutColor = gTempOutColor;
gOutText = gTempOutText;
gOut100Color = gTempOut100Color;
gOut100Text = gTempOut100Text;

gTempWindowOptions = [];
gTempListPosit = [];
gTempWindowLinkNum = [];
gTempInFace = [];
gTempInColor = [];
gTempInText = [];
gTempIn100Color = [];
gTempIn100Text = [];
gTempOutFace = [];
gTempOutColor = [];
gTempOutText = [];
gTempOut100Color = [];
gTempOut100Text = [];

}
else if (message == "Cancel")
{
//Stop the timer and Listener
llSetTimerEvent(0.0);
llListenRemove(gListenHandle);
llSay(0, "To remove the scripts from the windows simply say 'Die' on channel " + (string)WINDOW_SET_CHAN);

//Clear the temp lists
gTempWindowOptions = [];
gTempListPosit = [];
gTempWindowLinkNum = [];
gTempInFace = [];
gTempInColor = [];
gTempInText = [];
gTempIn100Color = [];
gTempIn100Text = [];
gTempOutFace = [];
gTempOutColor = [];
gTempOutText = [];
gTempOut100Color = [];
gTempOut100Text = [];
}
}
else if (channel == DIALOG_CHAN)
{

//First Check if we are setting/resetting the windows ...
if (message == "Reset" || message == "Set")
{
//Each window to be set needs a script ...
//The user touches the window ... Texture will change to numbers ...
//user says on window channel inside#@outside# then clicks again
//window resets scripts and passes data to contoller

llSay(0, "Touch each window to control, when the texture changes, ");
llSay(0, "say on channel " + (string)WINDOW_SET_CHAN + " the inside # followed by");
llSay(0, "the @ symbol, followed by the outside #. Then touch the window again.");
llSay(0, "Repeat the process for all windows, saying 'Done' on channel " + (string)RESET_CHAN + " when complete.");
llSay(0, "At anytime you may say 'Cancel' on channel " + (string)RESET_CHAN + " to stop the process.");

//Advise all the windows with the set script the linkid of this prim
llRegionSay(WINDOW_SET_CHAN, "link" + (string)llGetLinkNumber());

//Set up to Listen on reset channel, stoping the nomal Channel
llListenRemove(gListenHandle);
gListenHandle = llListen(RESET_CHAN,"",NULL_KEY,"");

//Set Timer to Turn off this channel if the user doesnt do anything ..
llSetTimerEvent(0);
llSetTimerEvent(1200.0);
}
else if (gCurDialog == CHECK_WINDOW)
{
//Hold the option selected
gWinSelected = message;

//Now Ask for the Tint .. setting the the proper dialog
gCurDialog = CHECK_TINT;
llDialog(id, "How much tint would you like?", TINT_OPTIONS, DIALOG_CHAN);
}
else if (gCurDialog == CHECK_TINT)
{
//Change the message into a number and hold it
if (message == "None")
{
gMsgTint = 0;
}
else
{
gMsgTint = (float)llGetSubString(message, 0, llStringLength(message)-2)/100;
}

//Set Next Dialog and show
gCurDialog = CHECK_SIDE;
llDialog(id, "Which sides would you like to tint?", SIDE_OPTIONS, DIALOG_CHAN);
}
else if (gCurDialog == CHECK_SIDE)
{
//Now we start tinting!!!
gCurDialog = NO_DIALOG;

//Stop Listening for the dialog
llSetTimerEvent(0.0);
llListenRemove(gListenHandle);

//Hold the sid modifier
gSideModifier = message;

call_windows();
}
}
} // end listen

timer()
{
//We have timed out ....
llSetTimerEvent(0.0);
llListenRemove(gListenHandle);
gCurDialog = NO_DIALOG;

}//End timer

} // end default
//
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
04-19-2008 19:05
I went over the script pretty good and I can't find anything that could possibly "change" the list orders.

Am wondering why you did this bit thou:

llListenRemove(gListenHandle);
gListenHandle = llListen(RESET_CHAN, "", NULL_KEY, "";);
llSetTimerEvent(0);
llSetTimerEvent(1200.0)

You changed from DIALOG_CHAN to RESET_CHAN but then removed the RESET_CHAN listen by calling llSetTimerEvent(0); but then recalled the timer event again with; llSetTimerEvent(1200.0)?

Other then that you are probably going to have to debug with llOwnerSay everywhere is the problem happens again. And wouldn't hurt to put a script out that will llOwnerSay everything on the channels you have chosen to make sure someone else isn't using one.

BTW, nice job on your coding, readable and neat!
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Shifting Dreamscape
Always questioning ...
Join date: 12 Dec 2007
Posts: 266
04-21-2008 01:32
Jesse ... first off it now seems to be working ... reconfigured and no errors for the last day .. am going to watch to see if it happens again .. but must have been a glitch in SL.

As to the timer ... at least from what I've read in the documentation, setting to 0 removes any prior set Timer events, not causing the event to occur. Then I reset it so that there is time to configure the windows. Is that not correct?