Object to Data v1.4
UNDER CONSTRUCTION! PLEASE WAIT!
(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)
Main_Main (Script)
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 = "";
}
}
}
}
}
Listen_Main (Script)
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();
}
}
}
}
Holo_Main (Script)
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());
}
}
}
}
Save Program (Script)
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();
}
}