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

From Second Life Wiki
Jump to navigation Jump to search
m (Object to Data v1.1 moved to Object to Data v1.2: Version changed to 1.2)
(Version 1.2 code added.)
Line 4: Line 4:


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.
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.
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:
<pre>
<pre>
Object To Data
To convert an object into data...
|
1) Place down the object you want to convert to data.
|---Object_Main (Script)
2) Drop the Data Main script into the object.
|---Listen (Object)
3) When told to, drop the Object to Data script into the object.
|---|
4) After the object finishes gathering data,  Re-Rez the object and then go to 'Tools' -> 'Set Scripts to Running in Selection', and then Re-Rez the object again.
|---|---Listen_Main(Script)
5) It will start to spew out data, copy this text in it's entirety and paste it into a note.
|---HoloBox (Object)
</pre><pre>
|---|
To convert data back to an object...
|---|---Holo_Main (Script)
1) Place the desired note into the Data to Object object, and then touch it.
|---|Data_Default (Note)
2) Stand back and wait for it to finish (this may take some time).
</pre>
</pre>


Now that you know how it works, start out by rezing a box and calling it "Data to Object", in it place an empty box called "HoloBox", as well as the following script.


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. 
Data to Object
<lsl>
key qid;
integer line = 0;
string  name = "Data_Default";
string allData;
integer prims;
vector start;




 
setLink() {
 
    list l = llParseString2List(allData, ["-=-"], []);
Main_Main (Script)
    vector pos = (vector)llList2String(l, 0);
<lsl>
    pos += start;
list data;
    while (llVecDist(llGetPos(), pos) > .01) llSetPos(pos);
key gSetupQueryId;
    list real;
integer gSetupNotecardLine = 0;
    integer i = 1;
string gSetupNotecardName = "Data_Default";
    while (i < llGetListLength(l)) {
string lastData;
        string this = llList2String(l, i);
 
        string thisPart = llGetSubString(this, 0, 1);
readSettingsNotecard() {
        if (thisPart == "#S") {
  gSetupNotecardLine = 0;
            real += (string)llGetSubString(this, 2, -1);
  gSetupQueryId = llGetNotecardLine(gSetupNotecardName,gSetupNotecardLine);  
        } else if (thisPart == "#K") {
            real += (key)llGetSubString(this, 2, -1);
        } else if (thisPart == "#I") {
            real += (integer)llGetSubString(this, 2, -1);
        } else if (thisPart == "#F") {
            real += (float)llGetSubString(this, 2, -1);
        } else if (thisPart == "#V") {
            real += (vector)llGetSubString(this, 2, -1);
        } else if (thisPart == "#R") {
            real += (rotation)llGetSubString(this, 2, -1);
        }
        i++;
    }
    llSetLinkPrimitiveParams(LINK_ALL_OTHERS, real);
}
}


default {
default {
     state_entry() {
     touch_start(integer i) {
         llListen(-5, "", "", "");
         start = llGetPos();
         llListen(-10, "", "", "");
         llOwnerSay("Start");
         llListen(1, "", "", "");
         llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
        llListen(-1, "", llGetOwner(), "");
        llPassTouches(0);
     }
     }
     touch_start(integer total_number) {
     run_time_permissions(integer p) {
         if (llDetectedKey(0) != llGetOwner())
         if (p & PERMISSION_CHANGE_LINKS) {
            return;
          line = 0;
        llDialog(llGetOwner(), "What do you want to do?", ["Save Program", "Run Program"], -1);
          qid = llGetNotecardLine(name,line);  
        }
     }
     }
     listen(integer i, string s, key id, string m) {
     dataserver(key queryId, string data) {
         if (i == -5)
         if (queryId == qid)  {
            llRezObject("Listen", llGetPos() + <0,0,2>, <0,0,0>, <0,0,0,0>, (integer)m);
            if (data != EOF) {
        if (i == -10) {
                line += 1;
            data += m;
                data = llList2String(llParseString2List(data, ["-----: "], []), 1);
            llSetTimerEvent(3);
                if (data == "#START#") {
        }
                    llRezObject("HoloBox", llGetPos() + <0,0,0>, <0,0,0>, <0,0,0,0>, 0);
        if (i == -1) {
                } else if (data == "#END#") {
            if (m == "Save Program") {
                    setLink();
                 llShout(-15, "Save Program");
                    llBreakAllLinks();
             }
                    allData = "";
            if (m == "Run Program") {
                } else {
                 readSettingsNotecard();
                    allData += data;
                 }
                qid = llGetNotecardLine(name,line);
             } else {
                 llSetTimerEvent(3);
             }
             }
         }
         }
     }
     }
     timer() {
     timer() {
         llOwnerSay("Copy and paste the following into a note and call it 'Data_' and some descriptor.");
         llOwnerSay("Done");
         llSetTimerEvent(0);
         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) {
     object_rez(key k) {
         if(queryId == gSetupQueryId)  {
         llCreateLink(k, 1);
            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 = "";
                }
            }
        }
     }
     }
}
}
Line 115: Line 105:




Listen_Main (Script)
Here are the two scripts required to turn an object into data:
 
Data Main
<lsl>
<lsl>
integer num = 0;
list total = [];
default {
default {
     on_rez(integer i) {
     state_entry() {
         llListen(i, "", "", "");
         llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
        if (llGetInventoryType("Object to Data") != -1) {
            state run;
        } else {
            llOwnerSay("Accept the permission to change links, and then place the 'Object to Data' script in me.");
        }
     }
     }
     listen(integer i, string n, key id, string m) {
     changed(integer num) {
         if (llGetOwnerKey(id) == llGetOwner()) {
         if (llGetInventoryType("Object to Data") != -1) {
             num++;
             state run;
            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;


state run {
    state_entry() {
        llOwnerSay("Gathering data... Please wait. This may take some time.");
        llSetText("Loading...", <1,1,1>, 1);
        integer num = llGetNumberOfPrims();
        list lst;
        integer i = 1;
        while (i <= num) {
            lst += llGetLinkKey(i);
            i++;
         }
         }
    }while(i);
        llBreakAllLinks();
    return result;
         i = 0;
}
        while (i < num) {
 
             llSetText((string)(((float)i*100.0)/((float)num)) + "% finished.", <1,1,1>, 1);
default {
             llGiveInventory(llList2Key(lst, i), "Object to Data");
    on_rez(integer i) {
             llCreateLink(llList2Key(lst, i), 1);
         llListen(i, "", "", "");
            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());
            }
           
           
           
         }
         }
        llSetText("", <1,1,1>, 1);
        llOwnerSay("Re-Rez this object and then go to 'Tools' -> 'Set Scripts to Running in Selection', and then Re-Rez this object again.");
        llRemoveInventory(llGetScriptName());
     }
     }
}
}
Line 241: Line 152:




Save Program (Script)
Object to Data
 
<lsl>
<lsl>
string SERIALIZER_DELIMITER = "$!#";
string hexc="0123456789ABCDEF";//faster
string hexc="0123456789ABCDEF";//faster


Line 268: Line 176:
}
}


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))))
string safeVector(vector v) {
    return "<"+safeFloat(v.x)+","+safeFloat(v.y)+","+safeFloat(v.z)+">";
}


                // floats get extra love
string safeRotation(rotation v) {
                result = Float2Hex(llList2Float(l, i));
    return "<"+safeFloat(v.x)+","+safeFloat(v.y)+","+safeFloat(v.z)+","+safeFloat(v.s)+">";
            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)
string safeFloat(float f) {
            {
    return Float2Hex(f);
                //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;
string list2string(list l) {
             }
    string ret;
    integer len = llGetListLength(l);
    integer i;
   
    while (i < len) {
        integer type = llGetListEntryType(l, i);
        if (type == 1) {
             ret += "#I"+(string)llList2Integer(l, i);
        } else if (type == 2) {
            ret += "#F"+safeFloat(llList2Float(l, i));
        } else if (type == 3) {
            ret += "#S"+llList2String(l, i);
        } else if (type == 4) {
            ret += "#K"+(string)llList2Key(l, i);
        } else if (type == 5) {
            ret += "#V"+safeVector(llList2Vector(l, i));       
        } else if (type == 6) {
            ret += "#R"+safeRotation(llList2Rot(l, i));
        }
        ret += "-=-";
        i++;
    }
    return ret;
}
 
string getTexture() {
    string ret;
   
    integer sides = llGetNumberOfSides();
   
    integer same = 1;
    list texture;
    list repeat;
    list offset;
    list rot;
   
    integer i = 0;
    while (i < sides) {
        list side  = llGetPrimitiveParams([PRIM_TEXTURE, i]);
        texture += llList2String(side, 0);
        repeat  += llList2Vector(side, 1);
        offset  += llList2Vector(side, 2);
        rot    += llList2Float(side, 3);
       
        if (!(llList2String(texture, i) == llList2String(texture, i-1) && llList2Vector(repeat, i) == llList2Vector(repeat, i-1) &&
            llList2Vector(offset, i) == llList2Vector(offset, i-1) && llList2Float(rot, i) == llList2Float(rot, i-1))) {
                same = 0;
        }
        i++;
    }
 
    if (same) {
        ret += list2string([PRIM_TEXTURE, ALL_SIDES, llList2String(texture, 0), llList2Vector(repeat, 0), llList2Vector(offset, 0), llList2Float(rot, 0)]);
    } else {
        integer j = 0;
        while (j < llGetListLength(texture)) {
            ret += list2string([PRIM_TEXTURE, j, llList2String(texture, j), llList2Vector(repeat, j), llList2Vector(offset, j), llList2Float(rot, j)]);
            j++;
        }
    }       
   
    return ret;
}
 
 
string getColor() {
    string ret;
 
    integer sides = llGetNumberOfSides();
   
    integer same = 1;
    list color;
    list alpha;
   
    integer i = 0;
    while (i < sides) {
        list side  = llGetPrimitiveParams([PRIM_COLOR, i]);
        alpha += llList2Float(side, 1);
        color  += llList2Vector(side, 0);
       
        if (!(llList2String(color, i) == llList2String(color, i-1) && llList2Vector(alpha, i) == llList2Vector(alpha, i-1))) {
                same = 0;
        }
        i++;
    }
 
    if (same) {
        ret += list2string([PRIM_COLOR, ALL_SIDES, llList2Vector(color, 0), llList2Float(alpha, 0)]);
    } else {
        integer j = 0;
        while (j < llGetListLength(color)) {
            ret += list2string([PRIM_COLOR, j, llList2Vector(color, j), llList2Float(alpha, j)]);
            j++;
        }
    }       
   
    return ret;
}
 
string getShiny() {
    string ret;
 
    integer sides = llGetNumberOfSides();
   
    integer same = 1;
    list shiny;
    list bump;
   
    integer i = 0;
    while (i < sides) {
        list side  = llGetPrimitiveParams([PRIM_BUMP_SHINY, i]);
        shiny += llList2Integer(side, 0);
        bump += llList2Integer(side, 1);
       
        if (!(llList2Integer(shiny, i) == llList2Integer(shiny, i-1) && llList2Integer(bump, i) == llList2Integer(bump, i-1))) {
                 same = 0;
        }
        i++;
    }
 
    if (same) {
        ret += list2string([PRIM_BUMP_SHINY, ALL_SIDES, llList2Integer(shiny, 0), llList2Integer(bump, 0)]);
    } else {
        integer j = 0;
        while (j < llGetListLength(shiny)) {
            ret += list2string([PRIM_BUMP_SHINY, j, llList2Integer(shiny, j), llList2Integer(bump, j)]);
             j++;
        }
    }       
   
    return ret;
}
string getBright() {
    string ret;
 
    integer sides = llGetNumberOfSides();
   
    integer same = 1;
    list fullbright;
   
    integer i = 0;
    while (i < sides) {
        list side  = llGetPrimitiveParams([PRIM_FULLBRIGHT, i]);
        fullbright += llList2Integer(side, 0);
       
        if (!(llList2Integer(fullbright, i) == llList2Integer(fullbright, i-1))) {
                same = 0;
        }
        i++;
    }
 
    if (same) {
        ret += list2string([PRIM_FULLBRIGHT, ALL_SIDES, llList2Integer(fullbright, 0)]);
    } else {
        integer j = 0;
        while (j < llGetListLength(fullbright)) {
            ret += list2string([PRIM_FULLBRIGHT, j, llList2Integer(fullbright, j)]);
            j++;
         }
         }
        return (string)type + (serialized_data = result = ",") + result + serialized_data;
    }       
   
    return ret;
}
 
vector getPos() {
    vector pos = llList2Vector(llGetPrimitiveParams([PRIM_POSITION]), 0);
    pos -= llList2Vector(llGetObjectDetails(llGetLinkKey(0), [OBJECT_POS]), 0);
    if (llGetLinkNumber() == 1) {
        pos = <0,0,0>;
     }
     }
     return "";
     return pos;
}
}


Say(integer i, string m) {
string getType() {
     llSleep(.15);
    list type = [PRIM_TYPE] + llGetPrimitiveParams([PRIM_TYPE]);
     llShout(i, m);
    type += [PRIM_PHYSICS] + llGetPrimitiveParams([PRIM_PHYSICS]);
    type += [PRIM_MATERIAL] + llGetPrimitiveParams([PRIM_MATERIAL]);
    type += [PRIM_TEMP_ON_REZ] + llGetPrimitiveParams([PRIM_TEMP_ON_REZ]);
    type += [PRIM_PHANTOM] + llGetPrimitiveParams([PRIM_PHANTOM]);
    type += [PRIM_ROTATION] + llGetPrimitiveParams([PRIM_ROTATION]);
    type += [PRIM_SIZE] + llGetPrimitiveParams([PRIM_SIZE]);
    type += [PRIM_FLEXIBLE] + llGetPrimitiveParams([PRIM_FLEXIBLE]);
    type += [PRIM_POINT_LIGHT] + llGetPrimitiveParams([PRIM_POINT_LIGHT]);
    type += [PRIM_CAST_SHADOWS] + llGetPrimitiveParams([PRIM_CAST_SHADOWS]);
    return list2string(type);
}
 
 
string getPrimitiveParams() {
     string ret;
    ret += getType();
     ret += getTexture();
    ret += getShiny();
    ret += getColor();
    ret += getBright();
    return ret;
}
}


default {
default {
     state_entry() {
     on_rez(integer i) {
         llListen(-15, "", "", "Save Program");
         if (llGetInventoryType("Replicate Main") == -1) {
    }
            string s = getPrimitiveParams();
    listen(integer i, string s, key id, string m) {
            s = safeVector(getPos()) + "-=-" + s;
        integer f = (integer)llFrand(10000) + 1691507124;
            llSetObjectName("-----");
        llShout(-5, (string)f);
            llSleep(llGetLinkNumber());
        llSleep(1);
            llOwnerSay("#START#");
        list total;
            integer i = 0;
        string tot;
            while (i < llStringLength(s)) {
        total = llGetPrimitiveParams([PRIM_TYPE]);
                llOwnerSay((string)llGetSubString(s, i, i+199));
        tot = serializeList(total);
                i += 200;
        Say(f, tot);
            }
        Say(f, (string)llGetColor(ALL_SIDES));
            llOwnerSay("#END#");
        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>
</lsl>
</lsl>


{{LSLC|Library}}
{{LSLC|Library}}

Revision as of 08:45, 27 April 2008

(http://www.gnu.org/copyleft/fdl.html) in the spirit of which this script is GPL'd. Copyright (C) 2008 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'm not one for writing documentation, so I apologize in advance for the confusion of the following.

To convert an object into data...
1) Place down the object you want to convert to data.
2) Drop the Data Main script into the object.
3) When told to, drop the Object to Data script into the object.
4) After the object finishes gathering data,  Re-Rez the object and then go to 'Tools' -> 'Set Scripts to Running in Selection', and then Re-Rez the object again.
5) It will start to spew out data, copy this text in it's entirety and paste it into a note.

To convert data back to an object... 1) Place the desired note into the Data to Object object, and then touch it. 2) Stand back and wait for it to finish (this may take some time).

Now that you know how it works, start out by rezing a box and calling it "Data to Object", in it place an empty box called "HoloBox", as well as the following script.

Data to Object <lsl> key qid; integer line = 0; string name = "Data_Default"; string allData; integer prims; vector start;


setLink() {

   list l = llParseString2List(allData, ["-=-"], []);
   vector pos = (vector)llList2String(l, 0);
   pos += start;
   while (llVecDist(llGetPos(), pos) > .01) llSetPos(pos);
   list real;
   integer i = 1;
   while (i < llGetListLength(l)) {
       string this = llList2String(l, i);
       string thisPart = llGetSubString(this, 0, 1);
       if (thisPart == "#S") {
           real += (string)llGetSubString(this, 2, -1);
       } else if (thisPart == "#K") {
           real += (key)llGetSubString(this, 2, -1);
       } else if (thisPart == "#I") {
           real += (integer)llGetSubString(this, 2, -1);
       } else if (thisPart == "#F") {
           real += (float)llGetSubString(this, 2, -1);
       } else if (thisPart == "#V") {
           real += (vector)llGetSubString(this, 2, -1);
       } else if (thisPart == "#R") {
           real += (rotation)llGetSubString(this, 2, -1);
       }
       i++;
   }
   llSetLinkPrimitiveParams(LINK_ALL_OTHERS, real);

}

default {

   touch_start(integer i) {
       start = llGetPos();
       llOwnerSay("Start");
       llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
   }
   run_time_permissions(integer p) {
       if (p & PERMISSION_CHANGE_LINKS) {
          line = 0;
          qid = llGetNotecardLine(name,line); 
       }
   }
   dataserver(key queryId, string data) {
       if (queryId == qid)  {
           if (data != EOF) {
               line += 1;
               data = llList2String(llParseString2List(data, ["-----: "], []), 1);
               if (data == "#START#") {
                   llRezObject("HoloBox", llGetPos() + <0,0,0>, <0,0,0>, <0,0,0,0>, 0);
               } else if (data == "#END#") {
                   setLink();
                   llBreakAllLinks();
                   allData = "";
               } else {
                   allData += data;
               }
               qid = llGetNotecardLine(name,line);
           } else {
               llSetTimerEvent(3);
           }
       }
   }
   timer() {
       llOwnerSay("Done");
       llSetTimerEvent(0);
   }
   object_rez(key k) {
       llCreateLink(k, 1);
   }

} </lsl>


Here are the two scripts required to turn an object into data:

Data Main <lsl> default {

   state_entry() {
       llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
       if (llGetInventoryType("Object to Data") != -1) {
           state run;
       } else {
           llOwnerSay("Accept the permission to change links, and then place the 'Object to Data' script in me.");
       }
   }
   changed(integer num) {
       if (llGetInventoryType("Object to Data") != -1) {
           state run;
       }
   }

}

state run {

   state_entry() {
       llOwnerSay("Gathering data... Please wait. This may take some time.");
       llSetText("Loading...", <1,1,1>, 1);
       integer num = llGetNumberOfPrims();
       list lst;
       integer i = 1;
       while (i <= num) {
           lst += llGetLinkKey(i);
           i++;
       }
       llBreakAllLinks();
       i = 0;
       while (i < num) {
           llSetText((string)(((float)i*100.0)/((float)num)) + "% finished.", <1,1,1>, 1);
           llGiveInventory(llList2Key(lst, i), "Object to Data");
           llCreateLink(llList2Key(lst, i), 1);
           i++;
       }
       llSetText("", <1,1,1>, 1);
       llOwnerSay("Re-Rez this object and then go to 'Tools' -> 'Set Scripts to Running in Selection', and then Re-Rez this object again.");
       llRemoveInventory(llGetScriptName());
   }

} </lsl>


Object to Data <lsl> 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 safeVector(vector v) {

   return "<"+safeFloat(v.x)+","+safeFloat(v.y)+","+safeFloat(v.z)+">";

}

string safeRotation(rotation v) {

   return "<"+safeFloat(v.x)+","+safeFloat(v.y)+","+safeFloat(v.z)+","+safeFloat(v.s)+">";

}

string safeFloat(float f) {

   return Float2Hex(f);

}

string list2string(list l) {

   string ret;
   integer len = llGetListLength(l);
   integer i;
   
   while (i < len) {
       integer type = llGetListEntryType(l, i);
       if (type == 1) {
           ret += "#I"+(string)llList2Integer(l, i);
       } else if (type == 2) {
           ret += "#F"+safeFloat(llList2Float(l, i));
       } else if (type == 3) {
           ret += "#S"+llList2String(l, i);
       } else if (type == 4) {
           ret += "#K"+(string)llList2Key(l, i);
       } else if (type == 5) {
           ret += "#V"+safeVector(llList2Vector(l, i));        
       } else if (type == 6) {
           ret += "#R"+safeRotation(llList2Rot(l, i));
       }
       ret += "-=-";
       i++;
   }
   return ret;

}

string getTexture() {

   string ret;
   
   integer sides = llGetNumberOfSides();
   
   integer same = 1;
   list texture;
   list repeat;
   list offset;
   list rot;
   
   integer i = 0;
   while (i < sides) {
       list side  = llGetPrimitiveParams([PRIM_TEXTURE, i]);
       texture += llList2String(side, 0);
       repeat  += llList2Vector(side, 1);
       offset  += llList2Vector(side, 2);
       rot     += llList2Float(side, 3);
       
       if (!(llList2String(texture, i) == llList2String(texture, i-1) && llList2Vector(repeat, i) == llList2Vector(repeat, i-1) &&
           llList2Vector(offset, i) == llList2Vector(offset, i-1) && llList2Float(rot, i) == llList2Float(rot, i-1))) {
               same = 0;
       }
       i++;
   }
   if (same) {
       ret += list2string([PRIM_TEXTURE, ALL_SIDES, llList2String(texture, 0), llList2Vector(repeat, 0), llList2Vector(offset, 0), llList2Float(rot, 0)]);
   } else {
       integer j = 0;
       while (j < llGetListLength(texture)) {
           ret += list2string([PRIM_TEXTURE, j, llList2String(texture, j), llList2Vector(repeat, j), llList2Vector(offset, j), llList2Float(rot, j)]);
           j++;
       }
   }        
   
   return ret;

}


string getColor() {

   string ret;
   integer sides = llGetNumberOfSides();
   
   integer same = 1;
   list color;
   list alpha;
   
   integer i = 0;
   while (i < sides) {
       list side  = llGetPrimitiveParams([PRIM_COLOR, i]);
       alpha += llList2Float(side, 1);
       color  += llList2Vector(side, 0);
       
       if (!(llList2String(color, i) == llList2String(color, i-1) && llList2Vector(alpha, i) == llList2Vector(alpha, i-1))) {
               same = 0;
       }
       i++;
   }
   if (same) {
       ret += list2string([PRIM_COLOR, ALL_SIDES, llList2Vector(color, 0), llList2Float(alpha, 0)]);
   } else {
       integer j = 0;
       while (j < llGetListLength(color)) {
           ret += list2string([PRIM_COLOR, j, llList2Vector(color, j), llList2Float(alpha, j)]);
           j++;
       }
   }        
   
   return ret;

}

string getShiny() {

   string ret;
   integer sides = llGetNumberOfSides();
   
   integer same = 1;
   list shiny;
   list bump;
   
   integer i = 0;
   while (i < sides) {
       list side  = llGetPrimitiveParams([PRIM_BUMP_SHINY, i]);
       shiny += llList2Integer(side, 0);
       bump += llList2Integer(side, 1);
       
       if (!(llList2Integer(shiny, i) == llList2Integer(shiny, i-1) && llList2Integer(bump, i) == llList2Integer(bump, i-1))) {
               same = 0;
       }
       i++;
   }
   if (same) {
       ret += list2string([PRIM_BUMP_SHINY, ALL_SIDES, llList2Integer(shiny, 0), llList2Integer(bump, 0)]);
   } else {
       integer j = 0;
       while (j < llGetListLength(shiny)) {
           ret += list2string([PRIM_BUMP_SHINY, j, llList2Integer(shiny, j), llList2Integer(bump, j)]);
           j++;
       }
   }        
   
   return ret;

} string getBright() {

   string ret;
   integer sides = llGetNumberOfSides();
   
   integer same = 1;
   list fullbright;
   
   integer i = 0;
   while (i < sides) {
       list side  = llGetPrimitiveParams([PRIM_FULLBRIGHT, i]);
       fullbright += llList2Integer(side, 0);
       
       if (!(llList2Integer(fullbright, i) == llList2Integer(fullbright, i-1))) {
               same = 0;
       }
       i++;
   }
   if (same) {
       ret += list2string([PRIM_FULLBRIGHT, ALL_SIDES, llList2Integer(fullbright, 0)]);
   } else {
       integer j = 0;
       while (j < llGetListLength(fullbright)) {
           ret += list2string([PRIM_FULLBRIGHT, j, llList2Integer(fullbright, j)]);
           j++;
       }
   }        
   
   return ret;

}

vector getPos() {

   vector pos = llList2Vector(llGetPrimitiveParams([PRIM_POSITION]), 0);
   pos -= llList2Vector(llGetObjectDetails(llGetLinkKey(0), [OBJECT_POS]), 0);
   if (llGetLinkNumber() == 1) {
       pos = <0,0,0>;
   }
   return pos;

}

string getType() {

   list type = [PRIM_TYPE] + llGetPrimitiveParams([PRIM_TYPE]);
   type += [PRIM_PHYSICS] + llGetPrimitiveParams([PRIM_PHYSICS]);
   type += [PRIM_MATERIAL] + llGetPrimitiveParams([PRIM_MATERIAL]);
   type += [PRIM_TEMP_ON_REZ] + llGetPrimitiveParams([PRIM_TEMP_ON_REZ]);
   type += [PRIM_PHANTOM] + llGetPrimitiveParams([PRIM_PHANTOM]);
   type += [PRIM_ROTATION] + llGetPrimitiveParams([PRIM_ROTATION]);
   type += [PRIM_SIZE] + llGetPrimitiveParams([PRIM_SIZE]);
   type += [PRIM_FLEXIBLE] + llGetPrimitiveParams([PRIM_FLEXIBLE]);
   type += [PRIM_POINT_LIGHT] + llGetPrimitiveParams([PRIM_POINT_LIGHT]);
   type += [PRIM_CAST_SHADOWS] + llGetPrimitiveParams([PRIM_CAST_SHADOWS]);
   return list2string(type);

}


string getPrimitiveParams() {

   string ret;
   ret += getType();
   ret += getTexture();
   ret += getShiny();
   ret += getColor();
   ret += getBright();
   return ret;

}

default {

   on_rez(integer i) {
       if (llGetInventoryType("Replicate Main") == -1) {
           string s = getPrimitiveParams();
           s = safeVector(getPos()) + "-=-" + s;
           llSetObjectName("-----");
           llSleep(llGetLinkNumber());
           llOwnerSay("#START#");
           integer i = 0;
           while (i < llStringLength(s)) {
               llOwnerSay((string)llGetSubString(s, i, i+199));
               i += 200;
           }
           llOwnerSay("#END#");
       }
   }

} </lsl> </lsl>