Object to Data v1.4
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
(http://www.gnu.org/copyleft/fdl.html) in the spirit of which this script is GPL'd. Copyright (C) 2007 Xaviar Czervik
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
I took the list serialize list code from someone, and it was posted on a wiki somewhere... (If this was you, please add your name so I can credit you).
I'm not one for writing documentation, so I apologize in advance for the confusion of the following.
Here is a map of the objects:
Object To Data | |---Object_Main (Script) |---Listen (Object) |---| |---|---Listen_Main(Script) |---HoloBox (Object) |---| |---|---Holo_Main (Script) |---|Data_Default (Note)
Now that everything is set up, drag the last script into every PRIM. No objects can be linked. Then, click Save Program. The objects WILL DELETE THEM SELF, so be careful. Copy and paste the text into a note, exactly as it appers in the chat log. No need to remove any dates, or the object name. Simply paste it.
Main_Main (Script)
<lsl>
list data;
key gSetupQueryId;
integer gSetupNotecardLine = 0;
string gSetupNotecardName = "Data_Default";
string lastData;
readSettingsNotecard() {
gSetupNotecardLine = 0; gSetupQueryId = llGetNotecardLine(gSetupNotecardName,gSetupNotecardLine);
}
default {
state_entry() { llListen(-5, "", "", ""); llListen(-10, "", "", ""); llListen(1, "", "", ""); llListen(-1, "", llGetOwner(), ""); llPassTouches(0); } touch_start(integer total_number) { if (llDetectedKey(0) != llGetOwner()) return; llDialog(llGetOwner(), "What do you want to do?", ["Save Program", "Run Program"], -1); } listen(integer i, string s, key id, string m) { if (i == -5) llRezObject("Listen", llGetPos() + <0,0,2>, <0,0,0>, <0,0,0,0>, (integer)m); if (i == -10) { data += m; llSetTimerEvent(3); } if (i == -1) { if (m == "Save Program") { llShout(-15, "Save Program"); } if (m == "Run Program") { readSettingsNotecard(); } } } timer() { llOwnerSay("Copy and paste the following into a note and call it 'Data_' and some descriptor."); llSetTimerEvent(0); integer i = 0; while (i < llGetListLength(data)) { llOwnerSay("\n" + llGetSubString(llList2String(data, i), 0, 250)); llOwnerSay("\n" + llGetSubString(llList2String(data, i), 251, -1)); i++; } } dataserver(key queryId, string data) { if(queryId == gSetupQueryId) { if(data != EOF) { gSetupNotecardLine += 1; gSetupQueryId = llGetNotecardLine(gSetupNotecardName,gSetupNotecardLine); if (llGetSubString(data, 0, 0) == "[") return; if (lastData == "") { lastData += data; } else { lastData += data; integer f = (integer)llFrand(10000) - 10000; llRezObject("HoloBox", llGetPos() + <0,0,2>, <0,0,0>, <0,0,0,0>, f); list lis = llParseString2List(lastData, ["-=!!=-"], []); integer i = 0; while (i < llGetListLength(lis)) { llSay(f, llList2String(lis, i)); i++; } lastData = ""; } } } }
} </lsl>
Listen_Main (Script) <lsl> integer num = 0; list total = [];
default {
on_rez(integer i) { llListen(i, "", "", ""); } listen(integer i, string n, key id, string m) { if (llGetOwnerKey(id) == llGetOwner()) { num++; total += m; if (num == 10) { llShout(-10, llDumpList2String(total, "-=!!=-")); llDie(); } } }
} </lsl>
Holo_Main (Script)
<lsl> string SERIALIZER_DELIMITER = "$!#"; integer num = 0;
list unserializeList(string serialized_data) {
// TODO: add some checking in-case we encounter a poorly formed serialization // consider using the same mem-packing list pushing technique used above // (want to run performace tests first) list result = []; list t; list l = llParseStringKeepNulls(serialized_data, [SERIALIZER_DELIMITER], []);
string item; integer i = (l != []);//This is a hack, it gets list lenght. integer type = 0; do { if((type = (integer)(item = llList2String(l, (i=~-i))))) {//Little error checking (also takes care of null strings). integer p = llSubStringIndex(item, ","); item = llDeleteSubString(item, 0, p); // How about those switch statements, Lindens??? if (TYPE_INTEGER == type) t = [(integer)item]; else if (TYPE_FLOAT == type) t = [(float)item]; else if (TYPE_STRING == type) t = [item]; else if (TYPE_KEY == type) t = [(key)item]; else { if (TYPE_ROTATION ^ type)// if (TYPE_VECTOR == type) t = [(vector)("<" + item + ">")]; else// if (TYPE_ROTATION == type) t = [(rotation)("<" + item + ">")]; } //when dealing with very long lists it might be advantagous to use the commented out line instead. //result = [result = t] + result; result = t + result;
} }while(i); return result;
}
default {
on_rez(integer i) { llListen(i, "", "", ""); } listen(integer i, string n, key id, string m) { if (llGetOwnerKey(id) == llGetOwner()) { list l = unserializeList(m); num++; if (num == 1) { list l2 = [PRIM_TYPE] + l; llSetPrimitiveParams(l2); } if (num == 2) { llSetColor((vector)m, ALL_SIDES); } if (num == 3) { llSetRot((rotation)m); } if (num == 4) { llSetScale((vector)m); } if (num == 5) { llSetTexture(m, ALL_SIDES); } if (num == 6) { vector t = (vector)m; llScaleTexture(t.x, t.y, ALL_SIDES); } if (num == 7) { vector t = (vector)m; llOffsetTexture(t.x, t.y, ALL_SIDES); } if (num == 8) { llRotateTexture((integer)m, ALL_SIDES); } if (num == 9) { list l2 = [PRIM_BUMP_SHINY, ALL_SIDES] + l; llSetPrimitiveParams(l2); } if (num == 10) { while (llVecDist(llGetPos(), (vector)m) > .1) llSetPos((vector)m); llRemoveInventory(llGetScriptName()); } } }
} </lsl>
Save Program (Script)
<lsl> string SERIALIZER_DELIMITER = "$!#";
string hexc="0123456789ABCDEF";//faster
string Float2Hex(float input) {// Copyright Strife Onizuka, 2006-2007, LGPL, http://www.gnu.org/copyleft/lesser.html
if((integer)input != input)//LL screwed up hex integers support in rotation & vector string typecasting {//this also keeps zero from hanging the zero stripper. float unsigned = llFabs(input);//logs don't work on negatives. integer exponent = llFloor(llLog(unsigned) / 0.69314718055994530941723212145818);//floor(log2(b)) + rounding error integer mantissa = (integer)((unsigned / (float)("0x1p"+(string)(exponent -= (exponent == 128)))) * 0x1000000);//shift up into integer range integer index = (integer)(llLog(mantissa & -mantissa) / 0.69314718055994530941723212145818);//index of first 'on' bit string str = "p" + (string)((exponent += index) - 24); mantissa = mantissa >> index; do str = llGetSubString(hexc,15&mantissa,15&mantissa) + str; while(mantissa = mantissa >> 4); if(input < 0) return "-0x" + str; return "0x" + str; }//integers pack well so anything that qualifies as an integer we dump as such, supports netative zero return llDeleteSubString((string)input,-7,-1);//trim off the float portion, return an integer
}
string serializeList(list l) {
integer i = (l != []);//This is a hack, it gets list lenght. if(i) { string serialized_data = ""; integer type = 0; string result; {@loop; // this custom loop is about as fast as a while loop. // we build the string backwords for memory reasons. // My kingdom for select statements....
if (TYPE_FLOAT == (type = llGetListEntryType(l, (i=~-i))))
// floats get extra love result = Float2Hex(llList2Float(l, i)); else if (TYPE_VECTOR == type) { vector v = llList2Vector(l, i); result = Float2Hex(v.x) + "," + Float2Hex(v.y) + "," + Float2Hex(v.z); } else if (TYPE_ROTATION == type) { rotation r = llList2Rot(l, i); result = Float2Hex(r.x) + "," + Float2Hex(r.y) + "," + Float2Hex(r.z) + "," + Float2Hex(r.s); } else //if ((TYPE_INTEGER == type) || (TYPE_STRING == type) || (TYPE_KEY == type)) result = llList2String(l, i);// integers, strings and keys required no voodoo
if(i) { //This came to me after reverse engeneering LSL bytecode, the realization that LSL memory management sucks. serialized_data = SERIALIZER_DELIMITER + (string)type + (serialized_data = result = ",") + result + serialized_data; jump loop; } } return (string)type + (serialized_data = result = ",") + result + serialized_data; } return "";
}
Say(integer i, string m) {
llSleep(.15); llShout(i, m);
}
default {
state_entry() { llListen(-15, "", "", "Save Program"); } listen(integer i, string s, key id, string m) { integer f = (integer)llFrand(10000) + 1691507124; llShout(-5, (string)f); llSleep(1); list total; string tot; total = llGetPrimitiveParams([PRIM_TYPE]); tot = serializeList(total); Say(f, tot); Say(f, (string)llGetColor(ALL_SIDES)); Say(f, (string)llGetRot()); Say(f, (string)llGetScale()); Say(f, (string)llGetTexture(ALL_SIDES)); Say(f, (string)llGetTextureScale(ALL_SIDES)); Say(f, (string)llGetTextureOffset(ALL_SIDES)); Say(f, (string)llGetTextureRot(ALL_SIDES)); total = llGetPrimitiveParams([PRIM_BUMP_SHINY, ALL_SIDES]); total = [llList2Integer(total, 0), llList2Integer(total, 1)]; tot = serializeList(total); Say(f, tot); Say(f, (string)(llGetPos())); llSleep(1); llDie(); }
} </lsl>