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

From Second Life Wiki
Jump to navigation Jump to search
m (Object to Data v1.2 moved to Object to Data v1.3: Version update.)
(Updated entire page.)
Line 1: Line 1:
{{LSL Header}}
{{LSL Header}}


(http://www.gnu.org/copyleft/fdl.html) in the spirit of which this script is GPL'd. Copyright (C) 2008 [[User:Xaviar Czervik|Xaviar Czervik]]
<div style="float:right;">__TOC__</div>
 
<div id="box">
== Introduction ==
<div style="padding: 0.5em;">
 
(http://www.gnu.org/copyleft/fdl.html) in the spirit of which this script is GPL'd. Copyright (C) 2009 [[User:Xaviar Czervik|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.
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 is one of the projects that I've spent a significant amount of time on, and that I've uploaded to the wiki.
It's purpose is simple: it allows anyone to transfer objects through text. This may seem trivial, but it has several advantages to it.
Below are a few ways in which this script can be used:
# The Internet. There is no way (yet) to go on to the Internet and request an object be sent to your SL character. This solves this issue. One could post the data on to the Internet, and allow people to copy the text down to SL, run this script, and obtain an object from it.
# Management Scripts. There is no way to have an object create a totally new object. And objects can only call llGiveInventory on other objects when in the same sim. This solves the issue by allowing objects to use email to send data, which can then be turned into an object.
</div></div>
<div id="box">
== Revision History ==
<div style="padding: 0.5em;">
Version 1.3:
# 100% success rate.
# Added PRIM_GLOW
# Added funcionality for multiple notecards (for really big objects).
# Improved effeciency; removed the delink/relink sections.
Version 1.2:
# Around 95% success rate.
# Changed to almost all llGetPrimitiveParams calls.
# Added more than just ten different descriptors of an object.
# Removed freekish menu-controled system.
# Script need only be dropped in root object, not every prim.
Version 1.1:
# Made process simpler: removed replicate from listen.
# Changed to work (slightly) better.
Version 1.0:
# First release.




Thanks to [[User:DMC Zsigmond|DMC Zsigmond]] for adding the documentation shown below.
</div></div>
 
<div id="box">
== Instructions ==
<div style="padding: 0.5em;">
 
Thanks to [[User:DMC Zsigmond|DMC Zsigmond]] for the original documentation shown below, modified for Version 1.3 by Xaviar.


Update: DMC Zsigmond 04/28/08 - "Supplementary Documentation"
-------------------------------------------------------------
-------------------------------------------------------------


Check List (Parts Required):
Check List (Parts Required):


1 x Script, named: "Data Main"
1 x Script, named: "Data To Object"
1 x Script, named: "Object to Data"
1 x Script, named: "Object to Data"
1 x Script, named: "Holo Script"
1 x Object, named: "HoloBox"
1 x Object, named: "HoloBox"
1 x Notecard, named: "Data Default"
1 x Notecard, named: "Data_Default"
Plus,
Plus,
1 x Any Object you wish to use these scripts with to turn into data, or re-rez it back again.
1 x Any Object you wish to use these scripts with to turn into data, or re-rez it back again.
Line 24: Line 69:
-------------------------------------------------------------
-------------------------------------------------------------


#) Select an Object you wish to turn into data (NB. perhaps start with a single object which is relatively simple).  
# Select an Object you wish to turn into data (NB. perhaps start with a single object which is relatively simple).  
#) Rez the Object you wish to turn into data on the ground.
# Rez the Object you wish to turn into data on the ground.
#) Right-click the Object you wish to turn into data, and select edit. Then click on the "Content" tab to view its contents.
# Right-click the Object you wish to turn into data, and select edit. Then click on the "Content" tab to view its contents.
#) Open your "Inventory", and create a new folder, called: "Object to Data v1.2".
# Open your "Inventory", and create a new folder, called: "Object to Data v1.3".
#) Under the new "Object to Data v1.2" folder, right-click and create a new script, named: "Data Main". Then copy and paste the "Data Main" LSL code on this wiki page into the "Data Main" script you just created under your "Object to Data v1.2" folder. Click on "Save" to compile the "Data Main" script,  and then after that "Data Main" script has successfully compiled, close the script.
# Under the new "Object to Data v1.3" folder, right-click and create a new script, named: Data To Object". Then copy and paste the "Data To Object" LSL code on this wiki page into the "Data To Object" script you just created under your "Object to Data v1.3" folder. Click on "Save" to compile the "Data to Object" script,  and then after that "Da to Object" script has successfully compiled, close the script.
#) Repeat Step 5, for both "Object to Data" and "Data to Object" scripts.
# Repeat Step 5, for both "Object to Data" and "Holo Script" scripts.
#) With the Object you wish to turn into data still selected, and with the "Content" tab highlighted/activated, drag'n'drop" the "Data Main" script you created in your Inventory, from your "Object to Data v1.2" folder into the "Contents" folder of the Object you wish to turn into data.
# With the Object you wish to turn into data still selected, and with the "Content" tab highlighted/activated, drag'n'drop" the "Object To Data" script you created in your Inventory, from your "Object to Data v1.3" folder into the "Contents" folder of the Object you wish to turn into data.
#) The Object you wish to turn into data will then prompt you with a "Blue Drop-Down Menu" asking you for permission to change the object's links. Accept the permission change by clicking on "YES" on the blue drop-down menu. Information for this permission request can also be viewed on your "Local Chat" window.
# Now drag'n'drop the "Object to Data" script you created in your Inventory, from your "Object to Data v1.3" folder into the "Contents" folder of the Object you wish to turn into data. Your Local Chat window will now inform you that the Object is gathering data, and to please wait...
#) Now drag'n'drop the "Object to Data" script you created in your Inventory, from your Object to Data v1.2 folder into the "Contents" folder of the Object you wish to turn into data. Your Local Chat window will now inform you that the Object is gathering data, and to please wait...
# Deselect the Object you wish to turn into data, and then right-click on it, and select, "Take", to take the object back into your inventory.
#) Deselect the Object you wish to turn into data, and then right-click on it, and select, "Take", to take the object back into your inventory.
# Locate your Object you wish to turn into data from within your "Inventory", and then re-rez it on the ground again.
#) Locate your Object you wish to turn into data from within your "Inventory", and then re-rez it on the ground again. After you re-rez it, it will begin outputting the first details of Object data in your Local Chat Window.  
# At this point, the Script Creator requests that you right-click on the "Object" you wish to turn into data and "select" it again.
#) At this point, the Script Creator, requests that you right-click on the "Object" you wish to turn into data and "select" it again.
# With the Object selected, go to your "Tools" menu on the Second Life browser, and select "Set Scripts to Running in Selection". A "Set Running Progress" dialogue box will pop up notifying you that the "Object to Data" script inside it, is running - and Done.  
#) With the Object selected, go to your "Tools" menu on the Second Life (tm) browser, and select "Set Scripts to Running in Selection". A "Set Running Progress" dialogue box will pop up notifying you that the "Object to Data" script inside it, is running - and Done.  
# Close this dialogue box, and then right-click on the Object you wish to turn into data and select, "Take" to take the object back into your Inventory for a 2nd time.
#) Close this dialogue box, and then right-click on the Object you wish to turn into data and select, "Take" to take the object back into your Inventory for a 2nd time.
# Locate your Object you wish to turn into data from within your "Inventory" for a 2nd time.
#) Locate your Object you wish to turn into data from within your "Inventory" for a 2nd time; however, this time, the Object you wish to turn into data WILL NOT APPEAR as the ORIGINAL OBJECT NAME, but instead, as a BLANK OBJECT, named with a  dash "-----".  
# Re-rez the Object on the ground for a final time. Wait a few moments (or possibly a minute or two) until your Local Chat Window outputs the Object's data.
#) Re-rez the Object named with a dash, "-----", on the ground for a final time. Wait a few moments until your Local Chat Window outputs the Object's data.
# Copy the text data from your Local Chat Window (including the time code) from the very beginning to the very end.
#) Copy the text data from your Local Chat Window (including the time code) from START to END:
# Return to your Inventory folder named, "Object to Data v1.3", and then right-click and create a new note (i.e. notecard) called, "Data_Default".
# Paste the Object code data copied from your Local Chat Window to the "Data_Default" notecard, and then "Save" it. This notecard now holds the data information for your Object.
# If the information does not fit in to one notecard, the first object stays named "Data_Default", however name the second notecard "Data_Default 1", the third "Data_Default 2", etc.


For example:
The entire object has now been turned into data. It can now be transferred through many means not usually possible, including a text file on the Internet.
<pre>
[5:43]  -----: #START#
[5:43]  -----: <0,0,0>-=-#I9-=-#I0-=-#I0-=-#V<0,1,0>-=-#F0-=-#V<0,0,0>-=-#V<0,0,0>-=-#V<0,0,0>-=-#I3-=-#I0-=-#I2-=-#I3-=-#I4-=-#I0-=-#I5-=-#I0-=-#I8-=-#R<0,0,0,1>-=-#I7-=-#V<0x900001p-21,0x900001p-21,0x900001p-21>-=
[5:43]  -----: -#I21-=-#I0-=-#I2-=-#F0x4CCCCDp-24-=-#F2-=-#F0-=-#F1-=-#V<0,0,0>-=-#I23-=-#I0-=-#V<1,1,1>-=-#F1-=-#F10-=-#F0x3p-2-=-#I24-=-#I0-=-#I17-=-#I-1-=-#S89556747-24cb-43ed-920b-47caed15465f-=-#V<1,1,0>-=-#V<0
[5:43]  -----: ,0,0>-=-#F0-=-#I19-=-#I-1-=-#I3-=-#I1-=-#I18-=-#I-1-=-#V<0,0,0>-=-#F1-=-#I20-=-#I-1-=-#I0-=-
[5:43]  -----: #END#
</pre>
#) Return to your Inventory folder named, "Object to Data v1.2", and then right-click and create a new note (i.e. notecard) called, "Data_Default".
#) Paste the Object code data copied from your Local Chat Window (i.e. as demonstrated above) to the "Data_Default" notecard, and then "Save" it. This notecard now holds the data information for your Object.
 
Furthermore, this "Data Default" notecard will later be required to be added to the contents of a new object called, "Data to Object", should you wish to turn your data back into an Object again.


End of Part 1/2.
End of Part 1/2.
Line 61: Line 97:
--------------------------------------------------------
--------------------------------------------------------


#) Create a new Object on the ground, and then right-click on it, and select "Edit".
# Create a new Object on the ground, and then right-click on it, and select "Edit".
#) Under the "General" tab, name the Object you just created as, "HoloBox". This object must be inserted into your "Data to Object" object in future to supply the prim that will be converted back into the original Object you once sort to have turned into text/notecard data.
# Under the "General" tab, name the Object you just created as, "HoloBox". This object must be inserted into your "Data to Object" object in future to supply the prim that will be converted back into the original Object you once sort to have turned into text/notecard data.
#) Right-click the "Holobox", and select "Take, to take the object back into your inventory.
# Go the the "Content" tab of the "HoloBox" prim, to view its contents.
#) Create a new Object on the ground, right-click it, and select "Edit".
# Drag'n'drop the "Holo Script" script under the "Object to Data v1.3" folder in your Inventory, to the "Contents" folder of the "HoloBox" object you have selected.
#) Under the "General" tab, name the Object you just created as, "Data to Object".
# Right-click the "HoloBox" object, and select "Take, to take the object back into your inventory.
#) Go the the "Content" tab of the "Data to Object" prim, to view its contents.
# Create a new Object on the ground, right-click it, and select "Edit".
#) Drag'n'drop the "Data To Object" script under the "Object to Data v1.2" folder in your Inventory, to the "Contents" folder of the "Data to Object" object you have selected.
# Under the "General" tab, name the Object you just created as, "Data to Object".
#) Drag'n'drop the "Holobox" object you have either in your "Objects" folder in your Inventory or under the "Object to Data v1.2" folder in your Inventory, to the "Contents" folder of the "Data to Object" object you have selected.  
# Go the the "Content" tab of the "Data to Object" prim, to view its contents.
#) Drag'n'drop the "Data_Default" notecard under the "Object to Data v1.2" folder in your Inventory, to the "Contents" folder of the "Data to Object" object you have selected.
# Drag'n'drop the "Data To Object" script under the "Object to Data v1.3" folder in your Inventory, to the "Contents" folder of the "Data to Object" object you have selected.
 
# Drag'n'drop the "HoloBox" object you have either in your "Objects" folder in your Inventory or under the "Object to Data v1.3" folder in your Inventory, to the "Contents" folder of the "Data to Object" object you have selected.  
With the "Content" tab highlighted/activated, and in the "Contents" folder of your object named, "Data to Object", you should now have the following items contained inside it:
# Drag'n'drop the "Data_Default" notecard(s) under the "Object to Data v1.3" folder in your Inventory, to the "Contents" folder of the "Data to Object" object you have selected.
 
# Confirm in the "Contents" folder of your object named "Data to Object", you now have the following items contained inside it: 1 x Script, named "Data to Object"; 1 (or as many as needed) x  Notecard(s), named "Data_Default" (with following numbers, if needed); and 1 x Object, named "HoloBox".
1 x Script, named: "Data to Object"
# Deselect the object, "Data to Object".
1 x  Notecard, named: "Data_Default"
# Now touch the object, "Data to Object" to begin rebuilding the original Object that you had turned into data. It can now be turned back into an Object again.
1 x Object, named: "HoloBox"
# View your Local Chat window for confirm of the build "Start", and notification when the build is "Done".
 
#) Deselect the object, "Data to Object".  
#) Now touch the object, "Data to Object" to begin rebuilding the original Object that you sort to have turned into data. It can now be turned back into an Object again.
#) A "Blue Drop-down Menu" will appear asking for permission to Link and de-link objects again. Select "YES" to accept and begin rebuilding.
#) View your Local Chat window for confirm of the build "Start", and notification when the build is "Done".


The original Object you sort to have turned into data will now rez as a new object above the "Data to Object" prim.  
The original Object you sort to have turned into data will now rez as a new object above the "Data to Object" prim.  
Line 86: Line 117:
This object will be empty, ready for use as intended.
This object will be empty, ready for use as intended.


End of Part 2/2 and DMC Zsigmond Update
End of Part 2/2


</pre>


I'm not one for writing documentation, so I apologize in advance for the confusion of the following.
</div></div>


To convert an object into data...
#) Place down the object you want to convert to data.
#) Drop the Data Main script into the object
#) When told to, drop the Object to Data script into the object.
#) 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.
#) 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...
<div id="box">
#) Place the desired note into the Data to Object object, and then touch it.
== Data To Object (Script) ==
#) Stand back and wait for it to finish (this may take some time).
<div style="padding: 0.5em;">


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.
<lsl>
string name = "Data_Default";


Data to Object
integer numberOfNotes;
<lsl>
key     qid;
key qid;
integer line = 0;
integer line = 0;
string  name = "Data_Default";
integer lineTotal = 0;
string allData;
integer prims;
integer prims;
list    totalLines;
integer totalLinesTotal;
string hexDigits = "0123456789ABCDEF";
integer rand;
integer whichNote;
vector start;
vector start;


get() {
    if (whichNote == 0) {
        qid = llGetNotecardLine(name, line);
    } else {
        qid = llGetNotecardLine(name + " " + (string)whichNote, line);
    }
       
}
rezObj(vector pos, string num) {
    while (llVecDist(llGetPos(), start-pos) > .001) llSetPos(start-pos);
    llRezObject("HoloBox", llGetPos(), <0,0,0>, <0,0,0,0>, hex2int(num) + rand);
}
integer hex2int(string hex) {
    integer p1 = llSubStringIndex(hexDigits, llGetSubString(hex, 0, 0));
    integer p2 = llSubStringIndex(hexDigits, llGetSubString(hex, 1, 1));
    integer data = p2 + (p1 << 4);
    return data;
}


setLink() {
default {
    list l = llParseString2List(allData, ["-=-"], []);
    touch_start(integer i) {
    vector pos = (vector)llList2String(l, 0);
        llSetText("Starting Up... (1/4)", <1,1,1>, 1);
    pos += start;
        numberOfNotes = llGetInventoryNumber(INVENTORY_NOTECARD);
    while (llVecDist(llGetPos(), pos) > .01) llSetPos(pos);
       
     list real;
        qid = llGetNumberOfNotecardLines(name);
    integer i = 1;
     }
     while (i < llGetListLength(l)) {
     dataserver(key queryId, string data) {
        string this = llList2String(l, i);
         if (queryId == qid) {
        string thisPart = llGetSubString(this, 0, 1);
             totalLines += data;
         if (thisPart == "#S") {
             totalLinesTotal += (integer)data;
             real += (string)llGetSubString(this, 2, -1);
             ++whichNote;
        } else if (thisPart == "#K") {
            if (whichNote < numberOfNotes) {
             real += (key)llGetSubString(this, 2, -1);
                llOwnerSay(name + " " + (string)whichNote);
        } else if (thisPart == "#I") {
                qid = llGetNumberOfNotecardLines(name + " " + (string)whichNote);
             real += (integer)llGetSubString(this, 2, -1);
            } else {
        } else if (thisPart == "#F") {
                state rez;
            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 {
state rez {
     touch_start(integer i) {
     state_entry() {
         start = llGetPos();
         start = llGetPos();
        rand = (integer)llFrand(0x6FFFFFFF) + 0x10000000;
         llOwnerSay("Start");
         llOwnerSay("Start");
         llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
         line = 0;
        qid = llGetNotecardLine(name, line);
        whichNote = 0;
     }
     }
     run_time_permissions(integer p) {
     dataserver(key queryId, string data) {
         if (p & PERMISSION_CHANGE_LINKS) {
         if (queryId == qid) {
          line = 0;
            if (data != EOF) {
          qid = llGetNotecardLine(name,line);  
                data = llList2String(llParseString2List(data, ["-----: "], []), 1);
                if (llGetSubString(data, 0, 3) == "#NEW") {
                    string num = llGetSubString(data, 5, 6);
                    vector pos = (vector)llGetSubString(data, 8, -1);
                    rezObj(pos, num);
                }
                llSetText("Rezing Prims: " + (string)((integer)(100*lineTotal/totalLinesTotal)) + "% (2/4)", <1,1,1>, 1);
                line += 1;
                lineTotal += 1;
                get();
            } else {
                whichNote++;
                if (whichNote < numberOfNotes) {
                    line = 0;
                    get();
                } else {
                    state run;
                }
            }
         }
         }
    }
}
state run {
    state_entry() {
        line = 0;
        lineTotal = 0;
        qid = llGetNotecardLine(name, line);
        whichNote = 0;
     }
     }
     dataserver(key queryId, string data) {
     dataserver(key queryId, string data) {
         if (queryId == qid)  {
         if (queryId == qid)  {
             if (data != EOF) {
             if (data != EOF) {
                data = llList2String(llParseString2List(data, ["-----: "], []), 1);
                if (llGetSubString(data, 0, 3) != "#NEW") {
                    list parts = llParseString2List(data, [":::"], []);
                    integer prim = hex2int(llList2String(parts, 0));
                    llRegionSay(rand + prim, llList2String(parts, 1));
                }
                llSetText("Sending Data: " + (string)((integer)(100*lineTotal/totalLinesTotal)) + "% (3/4)", <1,1,1>, 1);
                 line += 1;
                 line += 1;
                 data = llList2String(llParseString2List(data, ["-----: "], []), 1);
                 lineTotal += 1;
                 if (data == "#START#") {
                 get();
                    llRezObject("HoloBox", llGetPos() + <0,0,0>, <0,0,0>, <0,0,0,0>, 0);
            } else {
                 } else if (data == "#END#") {
                whichNote++;
                     setLink();
                 if (whichNote < numberOfNotes) {
                     llBreakAllLinks();
                     line = 0;
                    allData = "";
                     get();
                 } else {
                 } else {
                     allData += data;
                     llSetText("Cleaning Up... (4/4)", <1,1,1>, 1);
                    integer i = 0;
                    while (i < 256) {
                        llRegionSay(rand + i, "Finish");
                        ++i;
                    }
                    llSetTimerEvent(3);
                 }
                 }
                qid = llGetNotecardLine(name,line);
            } else {
                llSetTimerEvent(3);
             }
             }
         }
         }
     }
     }
     timer() {
     timer() {
        llSetText("Finished.", <1,1,1>, 1);
         llOwnerSay("Done");
         llOwnerSay("Done");
         llSetTimerEvent(0);
         llSetTimerEvent(0);
    }
         llResetScript();
    object_rez(key k) {
         llCreateLink(k, 1);
     }
     }
}
}
</lsl>
</lsl>


</div></div>




Here are the two scripts required to turn an object into data:
<div id="box">
== Replicate Main (Script) ==
<div style="padding: 0.5em;">


Data Main
<lsl>default {
<lsl>
default {
     state_entry() {
     state_entry() {
         llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
         llOwnerSay("Place the 'Object to Data' script in me.");
        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) {
     changed(integer num) {
Line 206: Line 287:
     }
     }
}
}


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




Object to Data
</div></div>
 
<div id="box">
== Object To Data (Script) ==
<div style="padding: 0.5em;">
<lsl>
<lsl>
string hexc="0123456789ABCDEF";//faster
string hexc="0123456789ABCDEF";//faster
Line 335: Line 421:
     return ret;
     return ret;
}
}


string getColor() {
string getColor() {
Line 404: Line 489:
     return ret;
     return ret;
}
}
string getBright() {
string getBright() {
     string ret;
     string ret;
Line 429: Line 515:
         while (j < llGetListLength(fullbright)) {
         while (j < llGetListLength(fullbright)) {
             ret += list2string([PRIM_FULLBRIGHT, j, llList2Integer(fullbright, j)]);
             ret += list2string([PRIM_FULLBRIGHT, j, llList2Integer(fullbright, j)]);
            j++;
        }
    }       
   
    return ret;
}
string getGlow() {
    string ret;
    integer sides = llGetNumberOfSides();
   
    integer same = 1;
    list glow;
   
    integer i = 0;
    while (i < sides) {
        list side  = llGetPrimitiveParams([PRIM_GLOW, i]);
        glow += llList2Integer(side, 0);
       
        if (!(llList2Integer(glow, i) == llList2Integer(glow, i-1))) {
                same = 0;
        }
        i++;
    }
    if (same) {
        ret += list2string([PRIM_GLOW, ALL_SIDES, llList2Integer(glow, 0)]);
    } else {
        integer j = 0;
        while (j < llGetListLength(glow)) {
            ret += list2string([PRIM_GLOW, j, llList2Integer(glow, j)]);
             j++;
             j++;
         }
         }
Line 455: Line 572:
     type += [PRIM_FLEXIBLE] + llGetPrimitiveParams([PRIM_FLEXIBLE]);
     type += [PRIM_FLEXIBLE] + llGetPrimitiveParams([PRIM_FLEXIBLE]);
     type += [PRIM_POINT_LIGHT] + llGetPrimitiveParams([PRIM_POINT_LIGHT]);
     type += [PRIM_POINT_LIGHT] + llGetPrimitiveParams([PRIM_POINT_LIGHT]);
    type += [PRIM_CAST_SHADOWS] + llGetPrimitiveParams([PRIM_CAST_SHADOWS]);
     return list2string(type);
     return list2string(type);
}
}
Line 467: Line 583:
     ret += getColor();
     ret += getColor();
     ret += getBright();
     ret += getBright();
    ret += getGlow();
     return ret;
     return ret;
}
}
string getMeta() {
    return llDumpList2String([llGetObjectName(), llGetObjectDesc()], "-=-");
}
string int2hex(integer num) {
    integer p1 = num & 0xF;
    integer p2 = (num >> 4) & 0xF;
    string data = llGetSubString(hexc, p2, p2) + llGetSubString(hexc, p1, p1);
    return data;
}
string meta;


default {
default {
     on_rez(integer i) {
     on_rez(integer i) {
         if (llGetInventoryType("Replicate Main") == -1) {
         meta = getMeta();
            string s = getPrimitiveParams();
        llSetObjectName("-----");
            s = safeVector(getPos()) + "-=-" + s;
        llOwnerSay("#NEW " + int2hex(llGetLinkNumber()) + " " + safeVector(llGetRootPosition()-llGetPos()));
            llSetObjectName("-----");
        string data = getPrimitiveParams();
            llSleep(llGetLinkNumber());
        llOwnerSay(int2hex(llGetLinkNumber()) + ":::0"+meta);
            llOwnerSay("#START#");
        integer i = 0;
            integer i = 0;
        integer num = 1;
            while (i < llStringLength(s)) {
        while (i < llStringLength(data)) {
                llOwnerSay((string)llGetSubString(s, i, i+199));
            llOwnerSay(int2hex(llGetLinkNumber()) + ":::" + (string)num + "" + (string)llGetSubString(data, i, i+199));
                i += 200;
            i += 200;
             }
             llSleep(.1);
             llOwnerSay("#END#");
             num++;
         }
         }
        llRemoveInventory(llGetScriptName());
     }
     }
}
}
</lsl>
</lsl>
</lsl>
 
 
</div></div>
 




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

Revision as of 19:06, 4 February 2009

Introduction

(http://www.gnu.org/copyleft/fdl.html) in the spirit of which this script is GPL'd. Copyright (C) 2009 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.

This is one of the projects that I've spent a significant amount of time on, and that I've uploaded to the wiki. It's purpose is simple: it allows anyone to transfer objects through text. This may seem trivial, but it has several advantages to it. Below are a few ways in which this script can be used:

  1. The Internet. There is no way (yet) to go on to the Internet and request an object be sent to your SL character. This solves this issue. One could post the data on to the Internet, and allow people to copy the text down to SL, run this script, and obtain an object from it.
  2. Management Scripts. There is no way to have an object create a totally new object. And objects can only call llGiveInventory on other objects when in the same sim. This solves the issue by allowing objects to use email to send data, which can then be turned into an object.


Revision History

Version 1.3:

  1. 100% success rate.
  2. Added PRIM_GLOW
  3. Added funcionality for multiple notecards (for really big objects).
  4. Improved effeciency; removed the delink/relink sections.

Version 1.2:

  1. Around 95% success rate.
  2. Changed to almost all llGetPrimitiveParams calls.
  3. Added more than just ten different descriptors of an object.
  4. Removed freekish menu-controled system.
  5. Script need only be dropped in root object, not every prim.

Version 1.1:

  1. Made process simpler: removed replicate from listen.
  2. Changed to work (slightly) better.

Version 1.0:

  1. First release.


Instructions

Thanks to DMC Zsigmond for the original documentation shown below, modified for Version 1.3 by Xaviar.


Check List (Parts Required):

1 x Script, named: "Data To Object" 1 x Script, named: "Object to Data" 1 x Script, named: "Holo Script" 1 x Object, named: "HoloBox" 1 x Notecard, named: "Data_Default" Plus, 1 x Any Object you wish to use these scripts with to turn into data, or re-rez it back again.


Part 1/2 - Instructions to convert an Object to Data


  1. Select an Object you wish to turn into data (NB. perhaps start with a single object which is relatively simple).
  2. Rez the Object you wish to turn into data on the ground.
  3. Right-click the Object you wish to turn into data, and select edit. Then click on the "Content" tab to view its contents.
  4. Open your "Inventory", and create a new folder, called: "Object to Data v1.3".
  5. Under the new "Object to Data v1.3" folder, right-click and create a new script, named: Data To Object". Then copy and paste the "Data To Object" LSL code on this wiki page into the "Data To Object" script you just created under your "Object to Data v1.3" folder. Click on "Save" to compile the "Data to Object" script, and then after that "Da to Object" script has successfully compiled, close the script.
  6. Repeat Step 5, for both "Object to Data" and "Holo Script" scripts.
  7. With the Object you wish to turn into data still selected, and with the "Content" tab highlighted/activated, drag'n'drop" the "Object To Data" script you created in your Inventory, from your "Object to Data v1.3" folder into the "Contents" folder of the Object you wish to turn into data.
  8. Now drag'n'drop the "Object to Data" script you created in your Inventory, from your "Object to Data v1.3" folder into the "Contents" folder of the Object you wish to turn into data. Your Local Chat window will now inform you that the Object is gathering data, and to please wait...
  9. Deselect the Object you wish to turn into data, and then right-click on it, and select, "Take", to take the object back into your inventory.
  10. Locate your Object you wish to turn into data from within your "Inventory", and then re-rez it on the ground again.
  11. At this point, the Script Creator requests that you right-click on the "Object" you wish to turn into data and "select" it again.
  12. With the Object selected, go to your "Tools" menu on the Second Life browser, and select "Set Scripts to Running in Selection". A "Set Running Progress" dialogue box will pop up notifying you that the "Object to Data" script inside it, is running - and Done.
  13. Close this dialogue box, and then right-click on the Object you wish to turn into data and select, "Take" to take the object back into your Inventory for a 2nd time.
  14. Locate your Object you wish to turn into data from within your "Inventory" for a 2nd time.
  15. Re-rez the Object on the ground for a final time. Wait a few moments (or possibly a minute or two) until your Local Chat Window outputs the Object's data.
  16. Copy the text data from your Local Chat Window (including the time code) from the very beginning to the very end.
  17. Return to your Inventory folder named, "Object to Data v1.3", and then right-click and create a new note (i.e. notecard) called, "Data_Default".
  18. Paste the Object code data copied from your Local Chat Window to the "Data_Default" notecard, and then "Save" it. This notecard now holds the data information for your Object.
  19. If the information does not fit in to one notecard, the first object stays named "Data_Default", however name the second notecard "Data_Default 1", the third "Data_Default 2", etc.

The entire object has now been turned into data. It can now be transferred through many means not usually possible, including a text file on the Internet.

End of Part 1/2.


Part 2/2 Instructions to convert Data to Object


  1. Create a new Object on the ground, and then right-click on it, and select "Edit".
  2. Under the "General" tab, name the Object you just created as, "HoloBox". This object must be inserted into your "Data to Object" object in future to supply the prim that will be converted back into the original Object you once sort to have turned into text/notecard data.
  3. Go the the "Content" tab of the "HoloBox" prim, to view its contents.
  4. Drag'n'drop the "Holo Script" script under the "Object to Data v1.3" folder in your Inventory, to the "Contents" folder of the "HoloBox" object you have selected.
  5. Right-click the "HoloBox" object, and select "Take, to take the object back into your inventory.
  6. Create a new Object on the ground, right-click it, and select "Edit".
  7. Under the "General" tab, name the Object you just created as, "Data to Object".
  8. Go the the "Content" tab of the "Data to Object" prim, to view its contents.
  9. Drag'n'drop the "Data To Object" script under the "Object to Data v1.3" folder in your Inventory, to the "Contents" folder of the "Data to Object" object you have selected.
  10. Drag'n'drop the "HoloBox" object you have either in your "Objects" folder in your Inventory or under the "Object to Data v1.3" folder in your Inventory, to the "Contents" folder of the "Data to Object" object you have selected.
  11. Drag'n'drop the "Data_Default" notecard(s) under the "Object to Data v1.3" folder in your Inventory, to the "Contents" folder of the "Data to Object" object you have selected.
  12. Confirm in the "Contents" folder of your object named "Data to Object", you now have the following items contained inside it: 1 x Script, named "Data to Object"; 1 (or as many as needed) x Notecard(s), named "Data_Default" (with following numbers, if needed); and 1 x Object, named "HoloBox".
  13. Deselect the object, "Data to Object".
  14. Now touch the object, "Data to Object" to begin rebuilding the original Object that you had turned into data. It can now be turned back into an Object again.
  15. View your Local Chat window for confirm of the build "Start", and notification when the build is "Done".

The original Object you sort to have turned into data will now rez as a new object above the "Data to Object" prim.

This object will be empty, ready for use as intended.

End of Part 2/2



Data To Object (Script)

<lsl> string name = "Data_Default";

integer numberOfNotes; key qid; integer line = 0; integer lineTotal = 0; integer prims; list totalLines; integer totalLinesTotal;

string hexDigits = "0123456789ABCDEF";

integer rand;

integer whichNote;

vector start;

get() {

   if (whichNote == 0) {
       qid = llGetNotecardLine(name, line);
   } else {
       qid = llGetNotecardLine(name + " " + (string)whichNote, line);
   }
       

}

rezObj(vector pos, string num) {

   while (llVecDist(llGetPos(), start-pos) > .001) llSetPos(start-pos);
   llRezObject("HoloBox", llGetPos(), <0,0,0>, <0,0,0,0>, hex2int(num) + rand);

}

integer hex2int(string hex) {

   integer p1 = llSubStringIndex(hexDigits, llGetSubString(hex, 0, 0));
   integer p2 = llSubStringIndex(hexDigits, llGetSubString(hex, 1, 1));
   integer data = p2 + (p1 << 4);
   return data;

}

default {

   touch_start(integer i) {
       llSetText("Starting Up... (1/4)", <1,1,1>, 1);
       numberOfNotes = llGetInventoryNumber(INVENTORY_NOTECARD);
       
       qid = llGetNumberOfNotecardLines(name);
   }
   dataserver(key queryId, string data) {
       if (queryId == qid)  {
           totalLines += data;
           totalLinesTotal += (integer)data;
           ++whichNote;
           if (whichNote < numberOfNotes) {
               llOwnerSay(name + " " + (string)whichNote);
               qid = llGetNumberOfNotecardLines(name + " " + (string)whichNote);
           } else {
               state rez;
           }
       }
   }

}

state rez {

   state_entry() {
       start = llGetPos();
       rand = (integer)llFrand(0x6FFFFFFF) + 0x10000000;
       llOwnerSay("Start");
       line = 0;
       qid = llGetNotecardLine(name, line); 
       whichNote = 0;
   }
   dataserver(key queryId, string data) {
       if (queryId == qid)  {
           if (data != EOF) {
               data = llList2String(llParseString2List(data, ["-----: "], []), 1);
               if (llGetSubString(data, 0, 3) == "#NEW") {
                   string num = llGetSubString(data, 5, 6);
                   vector pos = (vector)llGetSubString(data, 8, -1);
                   rezObj(pos, num);
               }
               llSetText("Rezing Prims: " + (string)((integer)(100*lineTotal/totalLinesTotal)) + "% (2/4)", <1,1,1>, 1);
               line += 1;
               lineTotal += 1;
               get();
           } else {
               whichNote++;
               if (whichNote < numberOfNotes) {
                   line = 0;
                   get();
               } else {
                   state run;
               }
           }
       }
   }

}

state run {

   state_entry() {
       line = 0;
       lineTotal = 0;
       qid = llGetNotecardLine(name, line); 
       whichNote = 0;
   }
   dataserver(key queryId, string data) {
       if (queryId == qid)  {
           if (data != EOF) {
               data = llList2String(llParseString2List(data, ["-----: "], []), 1);
               if (llGetSubString(data, 0, 3) != "#NEW") {
                   list parts = llParseString2List(data, [":::"], []);
                   integer prim = hex2int(llList2String(parts, 0));
                   llRegionSay(rand + prim, llList2String(parts, 1));
               }
               llSetText("Sending Data: " + (string)((integer)(100*lineTotal/totalLinesTotal)) + "% (3/4)", <1,1,1>, 1);
               line += 1;
               lineTotal += 1;
               get();
           } else {
               whichNote++;
               if (whichNote < numberOfNotes) {
                   line = 0;
                   get();
               } else {
                   llSetText("Cleaning Up... (4/4)", <1,1,1>, 1);
                   integer i = 0;
                   while (i < 256) {
                       llRegionSay(rand + i, "Finish");
                       ++i;
                   }
                   llSetTimerEvent(3);
               }
           }
       }
   }
   timer() {
       llSetText("Finished.", <1,1,1>, 1);
       llOwnerSay("Done");
       llSetTimerEvent(0);
       llResetScript();
   }

} </lsl>


Replicate Main (Script)

<lsl>default {

   state_entry() {
       llOwnerSay("Place the 'Object to Data' script in me.");
   }
   changed(integer num) {
       if (llGetInventoryType("Object to Data") != -1) {
           state run;
       }
   }

}


state run {

   state_entry() {
       llOwnerSay("Deploying scripts... 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++;
       }
       llSetScriptState("Object to Data", 0);
       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");
           i++;
       }
       llSetScriptState("Object to Data", 0);
       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 (Script)

<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;

} string getGlow() {

   string ret;
   integer sides = llGetNumberOfSides();
   
   integer same = 1;
   list glow;
   
   integer i = 0;
   while (i < sides) {
       list side  = llGetPrimitiveParams([PRIM_GLOW, i]);
       glow += llList2Integer(side, 0);
       
       if (!(llList2Integer(glow, i) == llList2Integer(glow, i-1))) {
               same = 0;
       }
       i++;
   }
   if (same) {
       ret += list2string([PRIM_GLOW, ALL_SIDES, llList2Integer(glow, 0)]);
   } else {
       integer j = 0;
       while (j < llGetListLength(glow)) {
           ret += list2string([PRIM_GLOW, j, llList2Integer(glow, 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]);
   return list2string(type);

}


string getPrimitiveParams() {

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

}

string getMeta() {

   return llDumpList2String([llGetObjectName(), llGetObjectDesc()], "-=-");

}

string int2hex(integer num) {

   integer p1 = num & 0xF;
   integer p2 = (num >> 4) & 0xF;
   string data = llGetSubString(hexc, p2, p2) + llGetSubString(hexc, p1, p1);
   return data;

}

string meta;


default {

   on_rez(integer i) {
       meta = getMeta();
       llSetObjectName("-----");
       llOwnerSay("#NEW " + int2hex(llGetLinkNumber()) + " " + safeVector(llGetRootPosition()-llGetPos()));
       string data = getPrimitiveParams();
       llOwnerSay(int2hex(llGetLinkNumber()) + ":::0"+meta);
       integer i = 0;
       integer num = 1;
       while (i < llStringLength(data)) {
           llOwnerSay(int2hex(llGetLinkNumber()) + ":::" + (string)num + "" + (string)llGetSubString(data, i, i+199));
           i += 200;
           llSleep(.1);
           num++;
       }
       llRemoveInventory(llGetScriptName());
   }

} </lsl>