LSL Examples

Scripts are also available in the TX Store (Coming Soon)

Server Script


/**
 * DNS Product Update Server:
 * Easy to setup product update system based on AnkaDNS (should take less than 1 min)
 * visit http://txgear.x10.mx/dns/
 * Why AnkaDNS?
 * Object URL's change randomly with every rez and sim-restart
 * We use ANKA DNS to mitigate this URL http://tx-gear.com/dns
 */

string private_key = ""; // Enter a private_key from http://txgear.x10.mx/dns/
string domain = "http://txgear.x10.mx";
string public_key;
integer timeout = 60;
string objUrl;
string qUrlUpdate;

string primtext;
vector cOk = <0, 1, 0>;//Everything is OK
vector cWarning = <1, 1, 0>;//Pending server request (Client Err)
vector cError = <1, 0, 0>;
integer giveTotal;
integer emailInterval = 1;

default
{
    state_entry()
    {
        //Set prim-text and object-name
        if (llGetObjectName() == "Object") {
            llSetObjectName(llGetScriptName());
            llSetText(llGetObjectName(), cWarning, TRUE);
        }
        
        if (!llStringLength(private_key)) {
            string msg;
            msg += "\nPRIVATE_KEY EMPTY! (line 6)";
            msg += "\nGo to http://txgear.x10.mx/dns/ to generate a key and add to your script.";
            llOwnerSay(msg);
            
        } else {
            // 1) generate a new prim-url
            llRequestURL();
        }
        
        llSetTimerEvent(timeout);
    }
    
    on_rez(integer num)
    {
        llResetScript();
    }
    
    changed(integer change)
    {
        if (change & CHANGED_INVENTORY) {
            llResetScript();
        }
    }
    
    http_request(key id, string method, string body)
    {
        if (method == URL_REQUEST_GRANTED) {
            objUrl = body;
            
            // 2) Post prim-url to server
            string data = llList2Json(JSON_OBJECT, [
                "private_key", private_key,
                "obj_url", body
            ]);
        
            qUrlUpdate = llHTTPRequest(domain + "/dns/api/", [
                HTTP_METHOD, "POST",
                HTTP_MIMETYPE, "application/x-www-form-urlencoded"
            ], data);
        }
    }
    
    http_response(key qId, integer status, list metadata, string body)
    {
        if (qId == qUrlUpdate) {
            // 3) Prim-url has been received by the server
            if (status== 404) {
                llOwnerSay("Error: " + llJsonGetValue(body, ["error"]));
                
            } else if (status == 200) {
                public_key = llJsonGetValue(body, ["public_key"]);
                llOwnerSay("Server Response:"
                    + "\n" + llJsonGetValue(body, ["motd"])
                    + "\n "
                    + "\nPublic Key: " + public_key
                );
                llSetText("Server is running", cOk, TRUE);
                state running;
            }
        }
    }
    
    timer()
    {
        llResetScript();
    }
}
    
state running
{
    state_entry()
    {
        llSetTimerEvent(emailInterval);
    }
    
    on_rez(integer num)
    {
        llResetScript();
    }
    
    changed(integer change)
    {
        if (change & CHANGED_REGION_START || change & CHANGED_INVENTORY) {
            state default;
        }
    }
    
    touch_end(integer num)
    {
        llOwnerSay("\nSERVER INFO"
            + "\ngiveTotal: " + (string)giveTotal
            + "\n"
            + "\nprivate_key: " + private_key
            + "\npublic_key: " + public_key
            + "\n"
            + "\nobj_url: " + objUrl
        );
    }
    
    http_request(key id, string method, string body)
    {
        //Extact sender information
        string owner = llGetHTTPHeader(id, "x-secondlife-owner-key");
        string ownerName = llGetHTTPHeader(id, "x-secondlife-owner-name");
        string objName = llGetHTTPHeader(id, "x-secondlife-object-name");
        
        //Split object name into segments
        list objSplit = llParseString2List(llToLower(objName), ["v"], [""]);
        
        //Extract last segment (version number)
        string objPrefix = llList2String(objSplit, 0);
        string objVersion = llList2String(objSplit, -1);
        
        //Split version number into segments
        list objVersionSegments = llParseString2List(objVersion, ["."], [""]);
        
        integer update;
        string invName;
        integer invIndex = llGetInventoryNumber(INVENTORY_OBJECT);
        while (invIndex-- && update == FALSE) {
            invName = llGetInventoryName(INVENTORY_OBJECT, invIndex);
            list invSplit = llParseString2List(llToLower(invName), ["v"], [""]);
            string invPrefix = llList2String(invSplit, 0);
            string invVersion = llList2String(invSplit, -1);
            list invVersionSegments = llParseString2List(invVersion, ["."], [""]);
            
            //Compare version segments
            if (objPrefix == invPrefix && objVersion != invVersion) {
                integer i;
                integer length = llGetListLength(invVersionSegments);
                for (i = 0; i < length; i++) {
                    if (llList2Integer(invVersionSegments, i) >= llList2Integer(objVersionSegments, i)) {
                        giveTotal++;
                        update = TRUE;
                    } else {
                        update = FALSE;
                        i = length;
                    }
                }
            }
        }
        
        //Respond to update request
        string msg;
        if (method == "GET" && update) {
            llSetText(ownerName + " got " + invName + "\nTotal Items Updated:" + (string)giveTotal, cOk, 1.0 );
            llGiveInventory(owner, invName);
            msg = "A update has been sent (" + invName + ")";
        } else {
            msg = "You are up-to-date";
        }
        
        llHTTPResponse(id, 200, msg);
    }
    
    timer()
    {
        llGetNextEmail("", public_key);
    }
    
    email( string time, string address, string subject, string message, integer num_left )
    {
        if (llGetSubString(address, -19, -1) == "@lsl.secondlife.com" && subject == public_key) {
            llEmail(address, public_key, objUrl);
        }
    }
}

Client Script

The client script connects to our API to get the server URL and object key.
This would allow the script to alternatively use email, instead of our API as a auxilary method


/**
 * DNS Product Update Client
 * Easy to setup product update system based on AnkaDNS (should take less than 1 min)
 * visit http://txgear.x10.mx/dns/
 *
 * Why AnkaDNS?
 * Object URL's change randomly with every rez and sim-restart
 * We use ANKA DNS to mitigate this URL http://txgear.x10.mx/dns/
 */

string public_key = "";
string domain = "http://txgear.x10.mx";

string objUrl;
string objKey;

string qGetUrl;
string qPingUrl;
integer pingFail;

// Use this function to send data to your inworld server
rcxPingUrl()
{
    qPingUrl = llHTTPRequest(objUrl, [
        HTTP_METHOD, "POST",
        HTTP_MIMETYPE, "application/x-www-form-urlencoded"
    ], "");// Add Custom data here
}

// Do no alter this function
rcxGetUrl()
{
    string data = llList2Json(JSON_OBJECT, [
        "public_key", public_key
    ]);
    
    qGetUrl = llHTTPRequest(domain + "/dns/api/", [
        HTTP_METHOD, "POST",
        HTTP_MIMETYPE, "application/x-www-form-urlencoded"
    ], data);
}

default
{
    state_entry()
    {
        if (llGetObjectName() == "Object") {
            llSetObjectName(llGetScriptName());
        }
        rcxGetUrl();    
    }
    
    on_rez(integer num)
    {
        rcxPingUrl();
    }
    
    link_message(integer sender_num, integer num, string msg, key id)
    {
        if (msg == "#update") {
            rcxPingUrl();
        }
    }
    
    http_response(key qId, integer status, list metadata, string body)
    {
        if (qId == qGetUrl) {
            if (status == 200) {
                objUrl = llJsonGetValue(body, ["obj_url"]);
                objKey = llJsonGetValue(body, ["obj_key"]);
                rcxPingUrl();
                
            } else if (status == 404) {
                llOwnerSay("Error: " + llJsonGetValue(body, ["error"]));
                
            }
            
        } else if (qId == qPingUrl) {
            
            if (status == 200) {
                pingFail = FALSE;
                
            } else if (status == 500) {
                pingFail++;
                if (pingFail == 1) {
                    rcxGetUrl();
                    
                } else {
                    llOwnerSay("HTTP Error: Falling Back On Email (If you don't see \"HTTP Updated\" in 40 seconds try again)");
                    llEmail(objKey + "@lsl.secondlife.com", public_key, "");
                    llSetTimerEvent(40);
                }
            }
        }
    }
    
    timer()
    {
        llGetNextEmail(objKey + "@lsl.secondlife.com", public_key);
        pingFail = FALSE;
        llSetTimerEvent(0);
    }
    
    email(string time, string address, string subject, string message, integer mailsLeft)
    {
        if (llGetSubString(address, -19, -1) == "@lsl.secondlife.com") {
            objUrl = llList2String(llParseString2List(message, ["\n\n"], [""]), 1);
            rcxPingUrl();
            llOwnerSay("HTTP Updated");
        }
    }
}