PASTE NAVIGATION MENU CODE

Wednesday 4 July 2012

Task 5: Communication

| | with 0 comments |
For this last installment in my blogs on Second Life, I will build two objects supporting outside-world communication. One will allow communication from the outside world into Second Life, and the other will allow Second Life to send data to the outside world. 

Communicating Inwards

For the icemalta.com area, it was decided to create an "Announcer" object. This object would receive data from the outside world and shout it within the icemalta area. This could be used to send general messages to the people in the icemalta area - use like a PA system in a department store.

First, a cube was created. This cube would eventually be sculpted to be shaped like a loud speaker. Then, the following LSL script was attached.

default{
    state_entry(){
        // Request URL
        llRequestURL();
    }
    http_request(key id, string method, string body){
        if (method == URL_REQUEST_GRANTED){
            llOwnerSay("My URL: " + body);
        }
        else if (method == URL_REQUEST_DENIED){
            llSay(0, "Something went wrong, no url. " + body);
        }
        else if (method == "GET"){
            // Get [GET] vars from header
            string get = llGetHTTPHeader(id, "x-query-string");

            // Split
            list get_parsed = llParseString2List(get, ["&"], [""]);
            integer i;
            integer pos = llGetListLength(get_parsed);
            llOwnerSay("\News From ICE:");           
                        
            for(i = 0; i < pos;i++){
                string str = (llList2String(get_parsed, i));
                string parsed =  llDumpList2String(llParseStringKeepNulls((str = "") + str, ["%20"], []), " ");
                llShout(0, parsed);
            }
            //Response (what you see in your browser)
            llHTTPResponse(id,200,"Message Sent to SL");
        } else{
            llHTTPResponse(id,405,"Unsupported Method");
        }
    }
}
When the object is created, it will say its SLURL to the owner.



The SLURL is the in-game URL of the object within Second Life. Every object within Second Life has its own URL, which can be used to communicate with the object. A user will then use this URL to send a message to Second Life. In this case, a GET parameter is being added directly to the URL in a browser, however this could easily be made to respond to a form - for example integrated into the icemalta intranet. 


When the URL is requested, the GET parameters are sent to the object. The object will loop through the parameters received and shout them within the area. Since web browsers convert spaces to the %20 key code, a function was used to replace these with spaces. 





Communicating Outwards 


Conversely, this next object allows Second Life to send data to the outside world. A service bell object is placed within the icemalta area. When the user touches the bell, a database record is created within the icemalta MySQL database which adds the username of the user requesting attention and the time the message was requested. A timer can then be implemented via AJAX which notifies ICE employees of incoming requests. The following LSL was attached to the attention bell.

integer SECRET_NUMBER={Hidden from blog};
string SECRET_STRING="{hidden from blog}"; 
key http_request_id;

xrequest(string url, list l){
    integer i;
    string body;
    integer len=llGetListLength(l) & 0xFFFE; // make it even
    for (i=0;i<len;i+=2){
        string varname=llList2String(l,i);
        string varvalue=llList2String(l,i + 1);
        if (i>0) body+="&";
        body+=llEscapeURL(varname)+"="+llEscapeURL(varvalue);
    }
    string hash=llMD5String(body+llEscapeURL(SECRET_STRING),SECRET_NUMBER);
    http_request_id = llHTTPRequest(url+"?hash="+hash,[HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"],body);
}

default{
    state_entry(){
        llSay(0, "Hi there! Press me for attention!");
    }
    touch_start(integer total_number){
        string name = llGetDisplayName(llDetectedKey(0));
        llSay(0, "Thank you " + name + " someone will be with you shortly!");
        xrequest("http://www.icemalta.com/slnotify.php",["sluser",name]);
    }
}
When the bell is touched, the player is notified that someone will shortly be with them. The name of the player is then sent as a parameter to the xrequest() function. This function will encode the username within a URL and make a request - in this case to icemalta.com/slnotify.php. To ensure the request is verified, a secret number and secret string (hidden from this blog) are needed. If these are incorrect or empty, the server-side PHP script ignores request.


<?php
  // this function tweak slightly urlencode to make it behave exactly like llEscapeURL in Second Life.
  function llEscapeURL($s){
    $s=str_replace(
      array(" ","+","-",".","_"),
      array("%20","%20","%2D","%2E","%5F"),
      urlencode($s));
    return $s;
  } 

  // this my main SL page XML-RPC page
  function checkHash(){
    global $body;
    $hash=$_GET["hash"];
    $body="";
    $cpt=0;
    $SECRET_NUMBER={hidden from blog};
    $SECRET_STRING={hidden from blog};

    foreach ($_POST as $name => $value) {
      if ($cpt++>0) $body.="&";
      if (get_magic_quotes_gpc()) {
        $value = stripslashes($value);
        $_POST[$name]=$value;
      }
      $body.=llEscapeURL($name)."=".llEscapeURL($value);
    }
    $calcHash=md5($body.$SECRET_STRING.':'.$SECRET_NUMBER);
    if ($hash!=$calcHash){
      sleep(2); // slow down the requests
      echo "result=FAIL\nMSG=Invalid request.";
      die;
    }
  }

  checkHash();
$pdo = new PDO(
    '{connection string hidden from blog}'
);

$qry = "INSERT INTO notifications (sluser) VALUES (\"" . $_POST['sluser']  . "\")";$pdo->query($qry);
mail('{hidden from blog}', 'E-mail from SL', $_POST['sluser']);
echo "OK";
?>

In the code above, the secret number and secret string will be checked. Then, the values received will be placed inside the $_POST[] PHP super global array. A connection to the database is then established using PHP Data Objects (PHP) and the data is posted into the database. Additionally, an e-mail is sent notifying the user of a new request. Perhaps in later versions this couch due changed to an instant message or a text message.


The notifications, as seen above, are then added to a MySQL database. A simple PHP script is then used to retrieve the list of pending notifications.

<?php
$pdo = new PDO(
    '{connection string hidden from blog}'
   $qry = "SELECT * FROM notifications ORDER BY ntime DESC";
   $result = $pdo->query($qry);
   while ($res = $result->fetch()) {
      echo $res['sluser'] . " at " . $res['ntime'];
   }
?>

In future releases, this can be integrated into the icemalta intranet including better graphics, direct links to the user location within Second Life, expiry and so on.

Post a Comment

Please enter your comments here..

0 comments: