Difference between revisions of "User:Opensource Obscure/FFHUD"

From Second Life Wiki
Jump to navigation Jump to search
(→‎Script: I really dislike this whitespacing model)
Line 48: Line 48:
* ...better code
* ...better code


<lsl>
<lsl>// FFHUD 0.7
// FFHUD 0.7
// free for public use
// free for public use
// A project started by Opensource Obscure
// A project started by Opensource Obscure
Line 89: Line 88:
key texturedefault = "4760a44f-06f7-622e-7429-b01570a598b0";
key texturedefault = "4760a44f-06f7-622e-7429-b01570a598b0";


 
//{ Combined Library - Copyright (C) 2004-2008, Strife Onizuka (cc-by 3.0) - "Jul 17 2008", "14:03:07"
// let's replace '&' with 'and'
string str_replace(string src, string from, string to)
string strReplace(string source, string pattern, string replace) {
{//replaces all occurrences of 'from' with 'to' in 'src'.
     while (llSubStringIndex(source, pattern) > -1) {
     integer len = llStringLength(from) - 1;
         integer len = llStringLength(pattern);
    if(len >= 0)
         integer pos = llSubStringIndex(source, pattern);
    {
         if (llStringLength(source) == len) { source = replace; }
        string  buffer = src;
        else if (pos == 0) { source = replace+llGetSubString(source, pos+len, -1); }
        integer b_pos = -1;
        else if (pos == llStringLength(source)-len) { source = llGetSubString(source, 0, pos-1)+replace; }
         integer to_len = llStringLength(to) - 1;
        else { source = llGetSubString(source, 0, pos-1)+replace+llGetSubString(source, pos+len, -1); }
        @loop;//instead of a while loop, saves 5 bytes (and runs faster).
         integer to_pos = 1 + llSubStringIndex(buffer, from);
         if(to_pos)
        {
//            b_pos += to_pos;
//            src = llInsertString(llDeleteSubString(src, b_pos, b_pos + len), b_pos, to);
//            b_pos += to_len;
//            buffer = llGetSubString(src, 1 + (b_pos), 0x40000000);
            buffer = llGetSubString(src = llInsertString(llDeleteSubString(src, b_pos += to_pos, b_pos + len), b_pos, to), 1 + (b_pos += to_len), 0x40000000);
            jump loop;
        }
     }
     }
     return source;
     return src;
}
}
 
//}


// partially redundant (1)
// partially redundant (1)
Line 120: Line 129:
     list lstParcelDesc=llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_DESC]);                 
     list lstParcelDesc=llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_DESC]);                 
     string a = (string)lstParcelDesc;   
     string a = (string)lstParcelDesc;   
     if(a != "00000000-0000-0000-0000-000000000000")
     if(a != NULL_KEY)
     {
     {
         desc = llDumpList2String(llParseString2List(a,[" "],[]),"+") + "+-+";                 
         desc = llDumpList2String(llParseString2List(a,[" "],[]),"+") + "+-+";                 
Line 128: Line 137:
         desc = "";
         desc = "";
     }  
     }  
     return strReplace(desc, "&", "and");   
     return str_replace(desc, "&", "and");   
}
}
   
   
Line 135: Line 144:
string parcelowner()
string parcelowner()
{
{
     list lstParcelOwner=llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_OWNER]);               
     return (string)llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_OWNER]);     
    string uuid = (string)lstParcelOwner;   
    return uuid;     
}
}
   
   
Line 144: Line 151:
string parcelgroup()
string parcelgroup()
{
{
     list lstParcelGroup=llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_GROUP]);             
     return (string)lstParcelGroup=llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_GROUP]);
    string uuid = (string)lstParcelGroup;
    return uuid;
}
}


Line 154: Line 159:
{
{
     string simname = llDumpList2String(llParseString2List(llGetRegionName(),[" "],[]),"+");
     string simname = llDumpList2String(llParseString2List(llGetRegionName(),[" "],[]),"+");
    string regionname = simname;
     vector detectedPos = llGetRootPosition();         
     vector detectedPos = llGetRootPosition();         
     string sx = (string)llRound(detectedPos.x);
     string sx = (string)llRound(detectedPos.x);
     string sy = (string)llRound(detectedPos.y);
     string sy = (string)llRound(detectedPos.y);
     string sz = (string)llRound(detectedPos.z);
     string sz = (string)llRound(detectedPos.z);
     string url = "http://slurl.com/secondlife/"
     return "http://slurl.com/secondlife/" + simname + "/" + sx + "/" + sy + "/" + sz;   
    url += simname;
    url += "/" + sx + "/" + sy + "/" + sz ;
    return url;   
}
}
   
   
Line 172: Line 173:
     llOwnerSay("parcel desc = " + (string)llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_DESC]));
     llOwnerSay("parcel desc = " + (string)llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_DESC]));
     llOwnerSay("parcel owner = " + "secondlife:///app/agent/" + parcelowner() + "/about");   
     llOwnerSay("parcel owner = " + "secondlife:///app/agent/" + parcelowner() + "/about");   
     llOwnerSay("parcel group = " + "secondlife:///app/group/" + parcelgroup() + "/about");
     llOwnerSay("parcel group = " + "secondlife:///app/group/" + parcelgroup() + "/about");
}
}


Line 240: Line 241:
     if(request_id == request_ff)  
     if(request_id == request_ff)  
         {
         {
        llOwnerSay(": Message sent.");
        llOwnerSay(": Message sent.");
         }
         }
      
      
Line 263: Line 264:
     changed(integer change)  
     changed(integer change)  
     {  
     {  
     if (change & (CHANGED_TELEPORT|CHANGED_REGION))
     if (change & (CHANGED_TELEPORT | CHANGED_REGION))
     {
     {
         llOwnerSay(": Location changed, restarting.");           
         llOwnerSay(": Location changed, restarting.");           
        state default;
        state default;
     }
     }
     }
     }
      
      
      
     timer()
  timer()
    {
  {
         llOwnerSay(": Time over.");         
         llOwnerSay(": Time over.");         
         state default;
         state default;
  }
    }
 
                      
                      
     touch_start(integer total_number)
     touch_start(integer total_number)
Line 284: Line 282:
         state default;         
         state default;         
     }  
     }  
   
      
      
     listen(integer channel, string name, key id, string message)
     listen(integer channel, string name, key id, string message)
Line 291: Line 288:
         state default;         
         state default;         
     }
     }
   


     // redundant (2)
     // redundant (2)
Line 298: Line 294:
     if(request_id == request_ff)  
     if(request_id == request_ff)  
         {
         {
        llOwnerSay(": Message sent.");
        llOwnerSay(": Message sent.");
         }
         }
      
      
     else if(request_id == request_texture)
     else if(request_id == request_texture)
         {
         {
         textureuuid = (key)llGetSubString(body,llSubStringIndex(body, code1)+llStringLength(code1),llSubStringIndex(body,code2)-3);
         textureuuid = (key)llGetSubString(body, llSubStringIndex(body, code1) + llStringLength(code1), llSubStringIndex(body,code2) - 3);
         llSetTexture(textureuuid, ALL_SIDES);
         llSetTexture(textureuuid, ALL_SIDES);
         }
         }
     }                                                                    
     }
 
}</lsl>
       
}
</lsl>

Revision as of 11:21, 17 July 2008

FFHUD: a simple FriendFeed HUD

by Opensource Obscure

Current release: 0.7
One-button, Custom messages, Rooms and Profile Image support.

FFHUD lets you post to FriendFeed. Posts always include a SLURL link to your actual location. You can send a quick update that automatically includes the parcel description, or write a custom message. If available, the owner or owner-group profile image is also published, accordingly to their privacy settings.

If you're on FriendFeed, you may want to join this room:
http://friendfeed.com/rooms/secondlife

Setup

  • Edit the script and put your FriendFeed account data. You may also specify a room.
  • Put the script in a prim (you may also want to rename it)
  • Wear the prim as an HUD

How to use FFHUD

  • Touch it once to get information about parcel you're in (printed in private chat via llOwnerSay)
  • Touch it again within 20 seconds to publish a post on FriendFeed... (that includes available info about the parcel: SLURL, description, owner/owner-group profile image)
  • ...or say a message on channel 8 within 20 seconds to publish a post (that includes same parcel info than above + your message) - Example:
/8 This is my message

Notes

Feel free to use this room for testing:
http://friendfeed.com/rooms/ffhud

FFHUD builds your posts this way:

  • LINK = SLURL of your location
  • TITLE = parcel name
  • COMMENT = parcel description (if available) OR your message
  • IMAGE = profile image of resident or group that owns the parcel
  • ROOM = according to your settings

FFHUD shows the FriendFeed favicon image by default; it changes (after the first touch) if a profile image is available for the parcel owners. Profile images are shown by using llSetTexture; the UUID is retrieved using the Second Life Search; the image web address (not the image itself) is sent to FriendFeed, that then retrieves and hosts a copy of the image.

Script

This code works but may be horrible and flawed. Feel free to suggest me how to improve it. I am not a real developer and I lack some programming basis, so any feedback can help me. I usually make the LSL scripts I need by reading around, cutting, pasting and tweaking code from other sources. To write FFHUD I used snippets by User:Ordinal Malaprop, User:Cory Linden, MarcoDuff Palen, User:Jana Kamachi and others.

To do:

<lsl>// FFHUD 0.7 // free for public use // A project started by Opensource Obscure //

// Look for your username and FriendFeed key here: https://friendfeed.com/account/api string user=""; // your FriendFeed username string ffkey=""; // your FriendFeed key

// You can send messages to a FriendFeed room: // "" -----------> default setting - you won't share messages to any room // "ffhud" ------> a test room you can freely use // "secondlife" -> an unofficial SL room - http://friendfeed.com/rooms/secondlife // Change accordingly the line below: string room="";


// after 1st click you have a few seconds to write and send // your text message before FFHUD comes back to default state. // you can change the timing below: float listentime = 20.0;


/////////////////////////////////////////////////// // you don't need to modify anything below


string desc; integer listen_handle; string baseurl="@friendfeed.com/api/share"; key request_ff; key request_texture; string ownerurl = "http://world.secondlife.com/resident/"; string groupurl = "http://world.secondlife.com/group/"; string code1 = "<img alt=\"profile image\" src=\"http://secondlife.com/app/image/"; string code2 = "\" class=\"parcelimg\" />"; key textureuuid = ""; key texturedefault = "4760a44f-06f7-622e-7429-b01570a598b0";

//{ Combined Library - Copyright (C) 2004-2008, Strife Onizuka (cc-by 3.0) - "Jul 17 2008", "14:03:07" string str_replace(string src, string from, string to) {//replaces all occurrences of 'from' with 'to' in 'src'.

   integer len = llStringLength(from) - 1;
   if(len >= 0)
   {
       string  buffer = src;
       integer b_pos = -1;
       integer to_len = llStringLength(to) - 1;
       @loop;//instead of a while loop, saves 5 bytes (and runs faster).
       integer to_pos = 1 + llSubStringIndex(buffer, from);
       if(to_pos)
       {

// b_pos += to_pos; // src = llInsertString(llDeleteSubString(src, b_pos, b_pos + len), b_pos, to); // b_pos += to_len; // buffer = llGetSubString(src, 1 + (b_pos), 0x40000000);

           buffer = llGetSubString(src = llInsertString(llDeleteSubString(src, b_pos += to_pos, b_pos + len), b_pos, to), 1 + (b_pos += to_len), 0x40000000);
           jump loop;
       }
   }
   return src;

} //}

// partially redundant (1) string parcelname() {

   list lstParcelName=llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_NAME]);                
   string a = (string)lstParcelName;
   string name = llDumpList2String(llParseString2List(a,[" "],[]),"+"); 
   return name; 

}


// partially redundant (1) // we use this after 2nd touch if no message is provided by the user string parceldesc() {

   list lstParcelDesc=llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_DESC]);                
   string a = (string)lstParcelDesc;  
   if(a != NULL_KEY)
   {
       desc = llDumpList2String(llParseString2List(a,[" "],[]),"+") + "+-+";                
   } 
   else
   {
       desc = "";
   } 
   return str_replace(desc, "&", "and");   

}


// partially redundant (1) string parcelowner() {

   return (string)llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_OWNER]);    

}


// partially redundant (1) string parcelgroup() {

   return (string)lstParcelGroup=llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_GROUP]);

}


// this comes from Cory Ondrejka I think string slurl() {

   string simname = llDumpList2String(llParseString2List(llGetRegionName(),[" "],[]),"+");
   vector detectedPos = llGetRootPosition();        
   string sx = (string)llRound(detectedPos.x);
   string sy = (string)llRound(detectedPos.y);
   string sz = (string)llRound(detectedPos.z);
   return "http://slurl.com/secondlife/" + simname + "/" + sx + "/" + sy + "/" + sz;   

}


// partially redundant (1) infoparcel() {

   llOwnerSay("parcel name = " + (string)llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_NAME]));
   llOwnerSay("parcel desc = " + (string)llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_DESC]));
   llOwnerSay("parcel owner = " + "secondlife:///app/agent/" + parcelowner() + "/about");   
   llOwnerSay("parcel group = " + "secondlife:///app/group/" + parcelgroup() + "/about");

}


texture() {

   if (parcelgroup() == parcelowner()) // group-owned land
   {
       request_texture = llHTTPRequest(groupurl + parcelgroup(),[HTTP_METHOD,"GET"],"");            
   }  
   else // group may be set, but land is not group-owned
       // single residents have pictures more often than group so we choose them
   { 
       request_texture = llHTTPRequest(ownerurl + parcelowner(),[HTTP_METHOD,"GET"],"");               
   }

}


string prepara(string messaggio) {

   string imageurl = "http://secondlife.com/app/image/" + (string)textureuuid + "/2";       
   messaggio = llDumpList2String(llParseString2List(messaggio,[" "],[]),"+");
   string post = 
   "http://" + 
   user + 
   ":" + 
   ffkey + 
   baseurl + 
   "?title=" + 
   parcelname() +
   "&link=" + 
   llEscapeURL(slurl()) + 
   "&comment=" +      
   messaggio +
   "&room=" +
   room +
   "&image0_url=" + 
   llEscapeURL(imageurl);
   return post;

}


default {

   on_rez(integer start_param)
   {
       llOwnerSay(": Ready. Touch once to get parcel info - Touch twice to update your FriendFeed page.");         
   }
   
   state_entry()
   {
       llSetTexture(texturedefault, ALL_SIDES);         
       llSetTimerEvent(0.0);                
   }
   
   
   touch_start(integer total_number)
   {      
       infoparcel();
       texture();
       state pronto;        
   }
   // redundant (2)
   http_response(key request_id, integer status, list metadata, string body)
   {
   if(request_id == request_ff) 
       {
       llOwnerSay(": Message sent.");
       }
   
   else if(request_id == request_texture)
       {
       textureuuid = (key)llGetSubString(body,llSubStringIndex(body, code1)+llStringLength(code1),llSubStringIndex(body,code2)-3);
       llSetTexture(textureuuid, ALL_SIDES);
       }
   }                                 

}


state pronto {

   state_entry()
   {
       llSetTimerEvent(listentime);        
       llOwnerSay(": Say your message on channel 8 within 20 seconds, or touch again to send a quick post.");        
       listen_handle = llListen(8, "", llGetOwner(), "");                
   }
   
   changed(integer change) 
   { 
   if (change & (CHANGED_TELEPORT | CHANGED_REGION))
   {
       llOwnerSay(": Location changed, restarting.");           
       state default;
   }
   }
   
   timer()
   {
       llOwnerSay(": Time over.");        
       state default;
   }
                   
   touch_start(integer total_number)
   {
       request_ff = llHTTPRequest(prepara(parceldesc()), [HTTP_METHOD,"POST"], ""); 
       state default;        
   } 
   
   listen(integer channel, string name, key id, string message)
   {
       request_ff = llHTTPRequest(prepara(message), [HTTP_METHOD,"POST"], ""); 
       state default;        
   }
   // redundant (2)
   http_response(key request_id, integer status, list metadata, string body)
   {
   if(request_id == request_ff) 
       {
       llOwnerSay(": Message sent.");
       }
   
   else if(request_id == request_texture)
       {
       textureuuid = (key)llGetSubString(body, llSubStringIndex(body, code1) + llStringLength(code1), llSubStringIndex(body,code2) - 3);
       llSetTexture(textureuuid, ALL_SIDES);
       }
   }

}</lsl>