Profile Greeter

Two years ago, gekkie Kidd got in touch with me to fix a “profile greeter” script that he got from a site somewhere (it’s long since gone). You know what that is… when a visitor comes near to a panel, all of a sudden, it displays their profile image for all to see. It’s supposed to be very popular on some clubs, or at least it was, back in 2009.

gekkie’s free script was badly mangled (or madly bangled? lol) and didn’t compile at all. I was intrigued. How do you know the texture ID that is on a profile page? That information isn’t supposed to be available at all. Nevertheless, there had to be some trick, because profile greeters everywhere definitely work…

Actually the trick was very basic and quite clever. Before Linden Lab introduced the new web profiles, there were already some web-based profiles in place. If you had someone’s UUID (which is easy to get!), you could see their in-world profiles with the following URL: (aye, that’s my own profile!). It was prettified with some LL-specific LSL, but still looked quite ugly, and that’s probably the reason why Linden Lab changed the Web-based profiles to things like, which are a bit better (and don’t require an UUID to be displayed).

The “old” Web-based profiles, however, have something nice: they retrieve the profile picture from LL’s database servers and convert it to a Web-readable format (yes, it’s a plain, old JPEG). But to do that they use… yes, you’ve guessed it: the image’s UUID!

In fact, pretty much every texture with enough permissions can be retrieved that way, not only profile pictures; this allowed for some nifty tools to display avatar profile pictures on Web pages. Or any other kind of textures really.

So, with this in mind, what gekkie’s script was attempting to do was to get an avatar’s UUID, make a Web call to the appropriate page, extract the image UUID by parsing the HTML, and retrieving the texture in-world, placing it on a prim’s face. Very cool! Once I figured this out, fixing the script — pretty much rewriting the unreadable bits and compiling it again — was a breeze.

Yesterday gekkie IM’ed me in despair because the script stopped working. Why? It was simple to explain: LL changed the HTML+CSS for the “old” Web-based profiles. To be more precise, now the image tag appears much lower on the code than before. Since you can only retrieve the first 2048 bytes from a Web page, LSL would never get at the image code. Drats! The script was failing with some silly errors for missing textures…

Well, I don’t know who at LL is responsible for that Web page, but they certainly deserve a medal. Or perhaps there were many complaints from Profile Greeter scripters, I don’t know. The point is that LL’s Web developers kindly added three meta tags at the very beginning of the header section: one for the agent UUID, one for the profile picture UUID, and the profile text itself. It looks like this (I’m using my own profile as an example):

Now that’s even simpler to parse! 🙂 Here is the final result. It uses a sensor to locate nearby avatars and display the profile picture of the nearest avatar in range. You can certainly elaborate on this script and make it more creative (some people display the avatar’s name on hovertext as well), but be warned: sensors are usually quite laggy. In the script below, it only scans in a radius of 20 metres around the prim, and repeats the scan every 10 seconds; if you wish to place a huge amount of those Profile Greeters in your club or home, it will lag crazily! Enjoy 🙂

 // tweaked by Gwyneth Llewelyn to use sensors string RESIDENT_URL = ""; key nameKey; vector curPos; default { state_entry() { llSetTexture(TEXTURE_BLANK, ALL_SIDES); nameKey = llGetOwner(); llHTTPRequest(RESIDENT_URL + (string)nameKey,[HTTP_METHOD,"GET"],""); // save current location curPos = llGetPos(); // start sensors llSensorRepeat("", NULL_KEY, AGENT, 20.0, TWO_PI, 10); } sensor(integer total_number) { vector current = llDetectedPos(0) -curPos; vector nearest = current; integer i; nameKey = llDetectedKey(0); for (i = 1; i < total_number; i++) { current = llDetectedPos(i); if (llVecDist(current, curPos) < llVecDist(nearest, curPos)) { nearest = current; nameKey = llDetectedKey(i); } } llHTTPRequest(RESIDENT_URL + (string)nameKey,[HTTP_METHOD,"GET"],""); } on_rez(integer start_param) { llResetScript(); } changed(integer what) { if ((what & CHANGED_SHAPE) || (what & CHANGED_SCALE)) llResetScript(); } http_response(key request_id,integer status, list metadata, string body) { if (llSubStringIndex(body, NULL_KEY) == -1) { integer start_of_UUID = llSubStringIndex(body,"<meta name=\"imageid\" content=\"") + llStringLength("<meta name=\"imageid\" content=\""); string profile_pic = llGetSubString(body, start_of_UUID, start_of_UUID + 35); llSetTexture((key)profile_pic, ALL_SIDES); } else { llWhisper(0, "You have no profile picture"); llSetTexture(TEXTURE_BLANK, ALL_SIDES); } } } // end default 

About Gwyneth Llewelyn

I'm just a virtual girl in a virtual world...

  • Demented Soul found a small bug on this script, there were two HTML entities appearing in it and showing up as “&amp;” which LSL cannot parse. Hrmpf. Well, I think I managed to fix that on this page…

  • Valentino Magnifico

    Stupid question. MY profile pic is very clear but other peoples pics are fuzzy even after a wait for it to rez. Any suggestions?

  • Mmh tricky question. Are they only fuzzy for you or for everybody around? If they’re only fuzzy for you, well, there are plenty of reasons for that, the usual one is that “waiting a bit” is not enough, and often clearing cache to force SL to reload the profile images again is the only choice. Then again, now that LL has added a few extra features on the viewer — like retrieving slightly-lower-quality compressed images to increase download speed and scene rendering time — I wonder if this is not related to your problem…