Managing menu access levels in LSL

Written by: Headmaster

If you are making a product that the final users could be a group of people and not only the owner then you need to let him manage the access levels somehow. For example you can let only group members access or maybe you can store the names in a notecard so the menu would be accessed by those listed in there. This script lets you build a menu where you can set up four different access levels:

  • Owner: only owner can access the menu
  • Group: agents that have the same group tag active as the object will have access to the menu
  • Anyone: …anyone can access
  • List: only those listed in a notecard will have access to the menu

In all cases obviously owner will have access. Lets take a look at the script:

 

list notecardsList;

integer listener;
integer mainMenuChannel;
integer accessChannel;

integer notecardLine;

string notecardName = "!access";

key query;

string access = "Owner";

list accessList;

integer randomNumber()
{
    return (integer)(llFrand(99999.0))*-1;
}

mainMenu(key id)
{
    llListenRemove(listener);
    mainMenuChannel = randomNumber();
    menu(id,mainMenuChannel,"Main menu",["Access"]);
}

menu(key user,integer channel,string title,list buttons)
{
    llListenRemove(listener);
    listener = llListen(channel,"","","");
    llDialog(user,title,buttons,channel);
    llSetTimerEvent(25.0);
}

accessMenu(key id)
{
    accessChannel = randomNumber();
    menu(id,accessChannel,"Access Menu " + "\n \n \n *Actual Access Level = " + access,["Owner","Group","Anyone","<< Back","List"]);
}

//Returns true if find is on src
integer isOnList(list src, list find)
{
     return (llListFindList(src,find) > -1);
}

//The function that checks if the toucher has access to the menu
integer checkAccess(key id)
{
    string name = llToLower(llKey2Name(id));

    return (id == llGetOwner()) || (llSameGroup(id) && access == "Group") || ( (isOnList(accessList,[name]) && (access == "List") ) || (access == "Anyone") );
}

default
{
    state_entry()
    {

        if (llGetInventoryType(notecardName) == INVENTORY_NOTECARD)
        {
            //A notecard named "!access" has been found, lets configure tha acess list
            llOwnerSay("Configuring, please wait...");
            notecardLine = 0;
            query = llGetNotecardLine(notecardName,notecardLine);
        }
        else
        {
            state ready;
        }
    }

    dataserver(key requested, string data)
    {
        if (requested == query)
        {
            if (data != EOF)
            {
                if ( (llGetSubString(data,0,0) != "#") && (data != "") ) //Ignore blank lines and lines starting with # (comments)
                {
                    string name = llToLower(llStringTrim(data,STRING_TRIM)); //Get the lowercase name and remove white space at from beginning and end if there are

                    if (llGetFreeMemory() >= 1024) //Script memory check
                    {
                        accessList = (accessList = []) + accessList + [name];
                    }
                    else
                    {
                        llOwnerSay(name + " could not be added because the script is running out of memory");
                        state ready;
                    }
                }
                notecardLine++;
                query = llGetNotecardLine(notecardName,notecardLine);
            }
            else
            {
                state ready;
            }
        }
    }

    on_rez(integer n)
    {
        if (llGetInventoryType("!config") == INVENTORY_TEXTURE)
        {
            llOwnerSay("Configuring, please wait...");
            notecardLine = 0;
            query = llGetNotecardLine(notecardName,notecardLine);
        }
        else
        {
            state ready;
        }
    }
}

state ready
{
    state_entry()
    {
        llOwnerSay("--- Ready ---");
    }

    changed (integer c)
    {
        if (c & CHANGED_INVENTORY)
        {
            //we assume that notecard was edited so reload the script
            llResetScript();
        }
    }

    touch_start(integer total_number)
    {
        key toucher = llDetectedKey(0);
        if (checkAccess(toucher))
        {
            mainMenu(toucher);
        }
        else
        {
            llSay(0,"Sorry you don't have access to the main menu, current access level: " + access);
        }
    }

    listen(integer channel, string name, key id, string message)
    {
        if (channel == mainMenuChannel)
        {
            if ( (message == "Access") && (id == llGetOwner())) //Only owner can access the Access Menu
            {
                accessMenu(id);
            }
            else
            {
                llSay(0,"Sorry, only owner can access to this menu");
            }
        }
        else if (channel == accessChannel)
        {
            if (message == "<< Back")
            {
                mainMenu(id);
                return;
            }

            access = message;
            llOwnerSay("Access Mode: " + message);
            accessMenu(id);
        }
    }

    timer()
    {
        llListenRemove(listener);
        llSetTimerEvent(0.0);
    }
} 

 

Get a copy of the script here

This script has no functionality at all but it’s a good structure for building a menu system with access level. It’s very easy to add new menus and options to it.

Note: the “Access” menu obviously can be accessed only by owner. Please post any questions that you may have.

 

Category: