Difference between revisions of "Object to Data v1.4"

From Second Life Wiki
Jump to navigation Jump to search
Line 131: Line 131:
The following object is called ObjectMakerFromNotecard. It has the following script and a note called Setup. (The data for setup will be given later).
The following object is called ObjectMakerFromNotecard. It has the following script and a note called Setup. (The data for setup will be given later).


<pre>
key gSetupQueryId;
key gSetupQueryId;
integer gSetupNotecardLine;
integer gSetupNotecardLine;
Line 175: Line 177:
     }
     }
}
}
</pre>




The following object is called ListenToReplicate. Place it in ObjectDataSaver.
The following object is called ListenToReplicate. Place it in ObjectDataSaver.


<pre>
integer num = 0;
integer num = 0;
list total = [];
list total = [];
Line 199: Line 203:
     }
     }
}
}
 
</pre>




The following code is for the ObjectDataSaver. It will also have and object called ListenToReplicate.
The following code is for the ObjectDataSaver. It will also have and object called ListenToReplicate.


<pre>
list data;
list data;


Line 226: Line 231:
     }
     }
}
}
 
</pre>


After you created the tree, drag the ObjectDataSaver down. Then place the following script in every prim of the object you want to save. Lastly, type any message on ch 1 and it will tell you the data. Then copy and paste it into a note called Setup and place it in the ObjectMakerFromNotecard.
After you created the tree, drag the ObjectDataSaver down. Then place the following script in every prim of the object you want to save. Lastly, type any message on ch 1 and it will tell you the data. Then copy and paste it into a note called Setup and place it in the ObjectMakerFromNotecard.
Line 232: Line 237:




<pre>
string SERIALIZER_DELIMITER = "$!#";
string SERIALIZER_DELIMITER = "$!#";


Line 328: Line 334:
     }
     }
}
}
</pre>

Revision as of 21:16, 15 May 2007

(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:

ObjectMakerFromNotecard
|
|---Setup (Notecard)
|---Main (Script)
|---Replicated (Object)
|---|
|---|---Main (Script)


ObjectDataSaver
|
|---Main (Script)
|---ListenToReplicate(Object)
|---|
|---|---Main (Script)


The following code goes in an object called Replicated. It is needed for the ObjectMakerFromNotecard.

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());
            }
            
            
            
        }
    }
}


The following object is called ObjectMakerFromNotecard. It has the following script and a note called Setup. (The data for setup will be given later).


key gSetupQueryId;
integer gSetupNotecardLine;
string  gSetupNotecardName = "Setup";


readSettingsNotecard() {
   gSetupNotecardLine = 0;
   gSetupQueryId = llGetNotecardLine(gSetupNotecardName,gSetupNotecardLine); 
}


default {
    state_entry() {
         readSettingsNotecard();
    }
    dataserver(key queryId, string data) {
        if(queryId == gSetupQueryId)  {
            if(data != EOF) {
                integer f = (integer)llFrand(10000) - 10000;
                llRezObject("Replicated", llGetPos() + <0,0,2>, <0,0,0>, <0,0,0,0>, f);
                list lis = llParseString2List(data, ["-=!!=-"], []);
                integer i = 0;
                while (i < llGetListLength(lis)) {
                    llSay(f, llList2String(lis, i));
                    i++;
                }
                gSetupQueryId = llGetNotecardLine(gSetupNotecardName,++gSetupNotecardLine); 
            } else {
                state running;   
            }
        }
    }        
    changed(integer change) {
        if (change&CHANGED_INVENTORY)
            llResetScript();
    }
}

state running {
    changed(integer change) {
        if (change&CHANGED_INVENTORY)
            llResetScript();
    }
}


The following object is called ListenToReplicate. Place it in ObjectDataSaver.

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();
            }
            
            
        }
    }
}


The following code is for the ObjectDataSaver. It will also have and object called ListenToReplicate.

list data;

default {
    state_entry() {
        llListen(-5, "", "", "");
        llListen(-10, "", "", "");
        llListen(1, "", "", "");
    }
    listen(integer i, string n, key id, string m) {
        if (i == -5)
            llRezObject("ListenToReplicate", llGetPos() + <0,0,2>, <0,0,0>, <0,0,0,0>, (integer)m);
        if (i == -10)
            data += m;
        if (i == 1) {
            integer i = 0;
            while (i < llGetListLength(data)) {
                llOwnerSay("\n" + llList2String(data, i));
                i++;
            }
        }
    }
}

After you created the tree, drag the ObjectDataSaver down. Then place the following script in every prim of the object you want to save. Lastly, type any message on ch 1 and it will tell you the data. Then copy and paste it into a note called Setup and place it in the ObjectMakerFromNotecard. (WARNING: EACH PRIM IS DELETED ONCE THE SCRIPT RUNS!!)


string SERIALIZER_DELIMITER = "$!#";

string hexc="0123456789ABCDEF";//faster

string Float2Hex(float a)
{// Copyright Strife Onizuka, 2006, LGPL, http://www.gnu.org/copyleft/lesser.html
    if(a)
    {
        float b = llFabs(a);
        integer c = llFloor(llLog(b) / 0.69314718055994530941723212145818);//floor(log2(b))
        if(c > 127) c = 127;//catch fatal rounding error in exponent.
        integer d = (integer)((b / llPow(2.0,c)) * 0x1000000);//shift up into integer range
        string f = "p";
        while(!(d & 0xf))
        {//strip extra zeros off before converting or they break "p"
            d = d >> 4;
            c+=4;
        }
        do
            f = llGetSubString(hexc, 0xf & d, 0xf & d) + f;
        while(d = d >> 4);
        if(a < 0)
            return "-0x" + f + (string)(c - 24);
        return "0x" + f + (string)(c - 24);
    }
    return "0";//zero would hang the zero stripper.
}

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() {
        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();
    }
}