Friday, September 9, 2011

RLV Scripting - Determine RLV version

Updated 9/15 - Thanks, Sei!

As I start to work with LSL a bit more, specifically with RLV, I thought I might share some scripts.

These first scripts will be for objects that are owned and worn by the avatar.  Interacting with furniture requires a relay and a slightly different way of doing things.

First thing, you should learn how to determine if RLV is present and enabled on the client.  The quickest way for one avatar to ask another avatar if they have RLV is to IM them "@version" (without the quotes).  If they have RLV on, they will auto-respond with the version number -- it won't even show up on their client.  If they don't have RLV, they're going to see that you sent them that message and probably ask what you're doing.

Scripts do this the same way, but they use llOwnerSay("@version=<channel>"); where channel is a channel your script is listening on.


This first script I call rlvCheck and it's meant to be called by another script wishing to know whether or not RLV is enabled and what version.  NOTE: This is an example script.  Bundle this into a larger script, or do more in just a single script to keep script counts down.

integer RLV_VERSION = 24767;
integer RLV_VERSION_REQUEST = 24768;
integer rlvCheckCount = 0;
integer rlvMaxCheck = 3;
float rlvCheckDelay = 30.0f;
integer rlvHandle;

checkRLV()
{
    rlvCheckCount = 0;
    rlvHandle = llListen(RLV_VERSION, "", llGetOwner(), "");
    llSetTimerEvent(rlvCheckDelay);
    llOwnerSay("@version=" + (string)RLV_VERSION);
}

default
{
    state_entry()
    {
        checkRLV(); // Do this to announce the RLV version to listening scripts in the same object
    }

timer()
{
    if (++rlvCheckCount >= rlvMaxCheck)
    {
        llListenRemove(rlvHandle);
        llSetTimerEvent(0.0f);
    }
    else
        llOwnerSay("@version=" +  (string)RLV_VERSION);
}

    listen(integer channel, string name, key id, string message)
    {
        if (channel == RLV_VERSION)
        {
            llListenRemove(rlvHandle);
            llSetTimerEvent(0.0f);

            string version = llList2String(llParseString2List(message, [" "], []), 2);
            list lTemp = llParseString2List(version, ["."], []);
            string major = llGetSubString(llList2String(lTemp, 0), -1, -1);
            string minor = llList2String(lTemp, 1);
            llMessageLinked(LINK_THIS, RLV_VERSION, major + minor, NULL_KEY);
        }
    }

    attach(key attached)
    {
        if (attached != NULL_KEY)
            checkRLV();
    }

    link_message(integer sender, integer msgType, string message, key id)
    {
        if (msgType == RLV_VERSION_REQUEST)
            checkRLV();
    }
}
A caller script that would use this might do something like:
integer RLV_VERSION = 24767;
integer RLV_VERSION_REQUEST = 24768;
integer rlvCapable = FALSE;
default
{
    state_entry()
    {
        llMessageLinked(LINK_THIS, RLV_VERSION_REQUEST, "", NULL_KEY);
    }

    link_message(integer sender_num, integer num, string message, key id)
    {
        if (num == RLV_VERSION)
        {
            rlvCapable = TRUE;
            llOwnerSay("Restrained Love v." + message + " detected");
            restoreRestrictions(); // a function to re-apply any restrictions
            return;
        }
    }
}
 Now at this point, the script will know if RLV is available after one and a half minutes.  What I usually do is cause RLV restrictions to be restored as soon as I know what the version is.

And the numbers I chose for the communication channel are just random ones I thought of -- there's nothing special or reserved about them.  I did found out that they can't be negative.