Don't click here unless you want to be banned.

LSL Wiki : LibraryInventoryMenuModule

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are crawling021.us.archive.org
Table of Contents

About

The module was developed to quickly allow for added inventory functionality. This module takes care of the dirty handling of the dialog boxes without requiring the scripter to do more then interpret the returned data.


Formating

The request and return data are specialy formated. There are two functions used to send and interpret the data dump and parse.

Request
integer InventoryMenuComm;
inventory_menu(key user, string message, float timeout, integer type,
        integer pos, integer mask, integer return_channel, list answer) {
    llMessageLinked(llGetLinkNumber(), InventoryMenuComm, dump([return_channel] + answer, "|"),
        dump([user, message, timeout, type, pos, mask], "|"));
}

Variable Type Description
InventoryMenuComm integer Channel that this module listens on, usualy a global variable
return_channel integer Channel that the return will come back on.
answer list This will be returned in the string paramater, when/if results come back
user key User to display the dialog box for
message string Message to prepend into the dialog boxes
timeout float Length of time the dialog box has to live before the script removes all information about the box
type integer Any INVENTORY_* flag, used to set which type of inventory the user is to pick
pos integer Given an inventory number will make the first dialog box show this inventory item
mask float Configuration mask for error handling and setup
ToP

Bit Mask Bits Return Description
0 0x001 -1 No inventory of specified type
1 0x002 -2 Target agent not found
2 0x004 -3 Target agent has left the sim
3 0x008 -4 Dialog box times out
4 0x010 -5 Queue being cleared
5 0x020 -6 Bad return channel
8 0x100 -5 via bit 4 Clears the queue then creates the dialog box
9 0x200 -5 via bit 4 Same as bit 4 but only for boxes for the current user
ToP
Return
llMessageLinked(
    link, 
    retchan, 
    dump(answer,"|"), 
    dump([value, name, type, type_count, user_key, user_name, time_left], "|")
);
ToP

Code

Core Tansport Functions
Paste these directly into your code for quick setup.
dumpUsed to take a list and convert it to a string, the seperator used is unique to the data (if possible)
parseParses the string from dump and quickdump back into a list
inventory_menuGenerate a valid session request

string dump(list a, string b) {
    string c = (string)a;
    if(1+llSubStringIndex(c,b) || llStringLength(b)!=1)
    {
        b += "|\\/?!@#$%^&*()_=:;~{}[],\n\" qQxXzZ";
        integer d = -llStringLength(b);
        while(1+llSubStringIndex(c,llGetSubString(b,d,d)) && d)
            ++d;
        b = llGetSubString(b,d,d);
    }
    return b + llDumpList2String(a, b);
}

list parse(string a) {
    string b = llGetSubString(a,0,0);//save memory
    return llParseStringKeepNulls(llDeleteSubString(a,0,0), [b],[]);
}

inventory_menu(key user, string message, float timeout, integer type,
        integer pos, integer mask, integer return_channel, list answer) {
    llMessageLinked(llGetLinkNumber(), InventoryMenuComm, dump([return_channel] + answer, "|"),
        dump([user, message, timeout, type, pos, mask], "|"));
}

integer InventoryMenuComm = 13;
ToP

Example
string dump(list a, string b) {
    string c = (string)a;
    if(1+llSubStringIndex(c,b) || llStringLength(b)!=1)
    {
        b += "|\\/?!@#$%^&*()_=:;~{}[],\n\" qQxXzZ";
        integer d = -llStringLength(b);
        while(1+llSubStringIndex(c,llGetSubString(b,d,d)) && d)
            ++d;
        b = llGetSubString(b,d,d);
    }
    return b + llDumpList2String(a, b);
}

list parse(string a) {
    string b = llGetSubString(a,0,0);//save memory
    return llParseStringKeepNulls(llDeleteSubString(a,0,0), [b],[]);
}

inventory_menu(key user, string message, float timeout, integer type,
        integer pos, integer mask, integer return_channel, list answer) {
    llMessageLinked(llGetLinkNumber(), InventoryMenuComm, dump([return_channel] + answer, "|"),
        dump([user, message, timeout, type, pos, mask], "|"));
}

integer InventoryMenuComm = 13;

default
{
    touch_start(integer a)
    {
        inventory_menu(llDetectedKey(0), "Choose something for me to give you:", 300, INVENTORY_ALL, 0, 0xFF, 1, []);
        llSay(0,"Choose something for me to give you");
    }
    link_message(integer a, integer b, string c, key d)
    {
        if(b == 1)
        {
            list e = parse(d);
            integer num = llList2Integer(d,0);
            if(num >= 0)
            {
                string name = llList2String(e,1);
                if(llGetInventoryPermMask(name, MASK_OWNER)) //change to use llGetInventoryType when added
                    llGiveInventory(name);
                else
                    llSay(0,"Object doesn't exist");
            }
            else
            {//an error has occured
                if(num == -1)
                    llSay(0,"No inventory to give of specified type");
                else if(num == -2)
                    llSay(0,"Agent could not be found in the sim");
                else if(num == -3)
                    llSay(0,"Agent has left the sim");
                else if(num == -4)
                    llSay(0,"Request timed out");
                else if(num == -5)
                    llSay(0,"Request removed, queue cleared");
            }
        }
    }
}
ToP

Inventory Menu Module
//////////////////////////////////////////////////////////////////////////////////////
//
//    Inventory Menu Module
//    Version 0.6 Release
//    Copyright (C) 2004-2005  Strife Onizuka
//    http://home.comcast.net/~mailerdaemon/
//    http://secondlife.com/badgeo/wakka.php?wakka=LibraryInventoryMenuModule
//    
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public License
//    as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//    
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Lesser General Public License for more details.
//    
//    You should have received a copy of the GNU Lesser General Public License
//    along with this library; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//    
//////////////////////////////////////////////////////////////////////////////////////
//{ Defaults: Change these if you want

//com is the second integer returned from link_message that it must match
integer InventoryMenuComm = 13;

//defaulttimeout is value used when a dialog box time to live is below the min time
//(mintime is hardcoded to 5 seconds)
integer defaulttimeout = 120;

//how often to check the for timeouts.
float ticksize = 5.0;

//number of buttons in a dialog box, unlikely to ever change but here anyway.
integer Buttons = 12;
//}
//////////////////////////////////////////////////////////////////////////////////////
//Don't change anything else unless you *really* need to.

//{mask values
//////////////////////////////////////////////////////////////////////////////////////
//
//0    0x001    -1              No inventory of specified type
//1    0x002    -2              Target agent not found
//2    0x004    -3              Target agent has left the sim
//3    0x008    -4              Dialog box times out
//4    0x010    -5              Queue being cleared
//5    0x020    -6              Bad return channel
//8    0x100    -5 via bit 4    Clears the queue then creates the dialog box
//9    0x200    -5 via bit 4    Same as bit 4 but only for boxes for the current user
//
//////////////////////////////////////////////////////////////////////////////////////
//}
//{global variables
list chans;     //listen channel
list handles;   //listen handle
list times;     //ttl

list masks;     //error/debug mask
list prims;     //prim to message
list intchans;  //integer channel to message on

list users;     //user keys
list answers;   //return list predefined
list types;     //inventory flag.

list messages;  //dialog box text
list buttons;   //buttons
list names;     //name of selected values
list values;    //inventory number

integer ticks;
//}
//{ msging
msglink(integer link, integer chan, string ans, list ret){
    if(chan != InventoryMenuComm)
        llMessageLinked(link, chan, ans, dump(ret, "|"));
}

inventory_menu(key user, string message, float timeout, integer type,
        integer pos, integer mask, integer retchan, list ret) {
    llMessageLinked(llGetLinkNumber(), InventoryMenuComm, dump([retchan] + ret, "|"),
        dump([user, message, timeout, type, pos, mask], "|"));
}
//}
//{ parse, dupm and quickdump
string quickdump(list a, string b){  return b + llDumpList2String(a, b); }

string dump(list a, string b) {
    string c = (string)a;
    if(1+llSubStringIndex(c,b) || llStringLength(b)!=1)
    {
        b += "|\\/?!@#$%^&*()_=:;~{}[],\n\" qQxXzZ";
        integer d = -llStringLength(b);
        while(1+llSubStringIndex(c,llGetSubString(b,d,d)) && d)
            d++;
        b = llGetSubString(b,d,d);
    }
    return b + llDumpList2String(a, b);
}

list parse(string a) {
    string b = llGetSubString(a,0,0);//save memory
    return llParseStringKeepNulls(llDeleteSubString(a,0,0), [b],[]);
}
//}
//{list cleanup
clear() {
    integer a = llGetListLength(handles);
    while(a--)
    {
        llListenRemove(llList2Integer(handles,a));
        if(llList2Integer(masks,a)&0x010)
        {
            integer b = llList2Integer(types,a);
            msglink(llList2Integer(prims,a), llList2Integer(intchans,a),
                    llList2String(answers,a), [-5, "", b, llGetInventoryNumber(b),
                    llList2Key(users,a), "", -1]);
        }
    }
    chans = handles = users = masks = intchans = prims = answers =
            types = messages = buttons = names = values = times = [];
    ticks = 0;
    llSetTimerEvent(0);
}

cleanup() {
    if(times == [])
    {
        chans = handles = users = masks = intchans = prims = answers =
                types = messages = buttons = names = values = times;
        llSetTimerEvent(0);
        ticks = 0;
    }
}

remove(integer a) {
    llListenRemove(llList2Integer(handles,  a));
    handles     = llDeleteSubList(handles,  a,a);
    times       = llDeleteSubList(times,    a,a);
    chans       = llDeleteSubList(chans,    a,a);
    users       = llDeleteSubList(users,    a,a);
    answers     = llDeleteSubList(answers,  a,a);
    prims       = llDeleteSubList(prims,    a,a);
    masks       = llDeleteSubList(masks,    a,a);
    intchans    = llDeleteSubList(intchans, a,a);
    types       = llDeleteSubList(types,    a,a);
    messages    = llDeleteSubList(messages, a,a);
    buttons     = llDeleteSubList(buttons,  a,a);
    names       = llDeleteSubList(names,    a,a);
    values      = llDeleteSubList(values,   a,a);
}
//}

generate(integer a, integer pos) {
    integer curType = llList2Integer(types, a);
    integer assets = llGetInventoryNumber(curType);
    if(assets == 1) {
        msglink(llList2Integer(prims,a), llList2Integer(intchans,a),
            llList2String(answers,a), [0, llGetInventoryName(curType,0), curType,
            assets, llList2Key(users,a), "",
            (llList2Float(times,a) - ticks) * ticksize]);
        remove(a);
    }
    else if(assets > 1) {
        if(pos > assets)    pos = assets;
        //{variables
        list text;
        list buts;
        list nam;
        list val;
        integer b;
        string d;
        string e;
        integer h;
        //}
        integer entries = Buttons;
        integer offset = (Buttons - 2) * ((pos - 1) / (Buttons - 2));
        if(assets <= Buttons)
            offset = 0;
        else if (offset && assets > Buttons) {
            offset++;
            val     += "";
            nam     += "-";
            buts    += "<Prev>";
            --entries;
        }
        if(assets - offset > entries)
            --entries;
        for(;(h=(b+offset))<assets && b<entries;++b) {
            val     += h;
            nam     += (d = llGetInventoryName(curType, h));
            text    += (e = (llGetSubString("ABCDEFGHJKLMN",b,b) + ": " + d));
            buts    += llGetSubString(e,0,15);
        }
        if(entries + (offset!=0) + 1 == Buttons) {
            val     += "";
            nam     += "+";
            buts    += "<Next>";
        }
        
        integer cat     =    -255 - (integer)llFrand(0x7FFFFF00);
        while(1+llListFindList(chans,[cat]))
            --cat;
        llListenRemove(llList2Integer(handles, a));
        key user = llList2Key(users,a);
        values  = llListReplaceList(values, [dump(val,"^")],a,a);
        names   = llListReplaceList(names,  [dump(nam,"^")],a,a);
        buttons = llListReplaceList(buttons,[dump(buts,"^")],a,a);
        chans   = llListReplaceList(chans,  [cat], a,a);
        handles = llListReplaceList(handles,[llListen(cat,"",user,"")], a,a);
        
        llDialog(user, llList2String(messages,a)+dump(text, "\n"),
                    buts, llList2Integer(chans,a));
    }
    else if(llList2Integer(masks,a) & 0x001) {
        msglink(llList2Integer(prims,a), llList2Integer(intchans,a),
            llList2String(answers,a),
            [-1, "", curType, assets, llList2Key(users,a), "", -1]);
        remove(a);
    }
}

default {
    state_entry() {
        llOwnerSay("Inventory Menu Module, Version 0.6, " +
            "Released Under the GNU Lesser General Public License");
        llOwnerSay("Copyright (C) 2004-2005 Strife Onizuka");
        if(ticksize < 2.5)
            ticksize = 2.5;
    }
    on_rez(integer a) {
        clear();
    }
    link_message(integer a, integer b, string c, key d) {
        if(b==InventoryMenuComm)
        {
            b = llSubStringIndex(llDeleteSubString(c,0,0), llGetSubString(c,0,0));
            list    e = parse(d);        //user, message, timeout, type, pos, mask
            key     user    =    llList2String(e,0);
            integer type    =    (integer)llList2String(e,3);
            integer mask    =    (integer)llList2String(e,5);
            integer chan    =    (integer)llDeleteSubString(c, b + 1, 0);
            if(user == "" || user == NULL_KEY) user = llGetOwner(); //lazy check
            
            //{cleanup
            if(mask & 0x100)
                clear();
            else if(mask & 0x200)
            {//clean out other box's that went to this user.
                while(1 + (b = llListFindList(users, [user])))
                {
                    if(llList2Integer(masks,b)&0x010)
                    {
                        integer f = llList2Integer(types, b);
                        msglink(llList2Integer(prims,b), llList2Integer(intchans,b), 
                            llList2String(answers,b), [-5, "", f,
                            llGetInventoryNumber(f), llList2Key(users,b), "", -1]);
                    }
                    remove(b);
                }
            }
            cleanup();
            //}
            
            //{Fatal Errors 
            if(!llGetInventoryNumber(type))
            {
                if(mask & 0x001)
                    msglink(a, chan, llDeleteSubString(c,0,b),
                            [-1, "", type, llGetInventoryNumber(type), user, "", -1]);
                return;
            }
            else if(llGetAgentSize(user) == ZERO_VECTOR) 
            {// target not in the sim
                if(mask & 0x002)
                    msglink(a, chan, llDeleteSubString(c,0,b),
                            [-2, "", type, llGetInventoryNumber(type), user, "", -1]);
                return;
            }//}
            else
            {//all fatal errors handled.
                integer h       =    (integer)llFrand(0x7FFFFF00);
                float   timeout =    (float)llList2String(e,2);
                
                if(timeout < 5.0 || timeout > 7200)
                    timeout = defaulttimeout;
                while(1+llListFindList(handles,[h]))
                    --h;
                
                chans       +=  0;
                handles     +=  h;
                times       +=  (ticks + (timeout / ticksize));
                
                masks       +=  mask;
                prims       +=  a;
                intchans    +=  chan;
                
                users       +=  user;
                answers     +=  llDeleteSubString(c,0,b);
                types       +=  type;
                
                messages    +=  llList2String(e,1);
                buttons     +=  "";
                names       +=  "";
                values      +=  "";
                llSetTimerEvent(ticksize);
                generate(-1, (integer)llList2String(e,4));
            }
        }
    }
    listen(integer a, string b, key c, string d) {
        a=llListFindList(chans,[a]);
        if(a+1 && llList2Key(users,a) == c)
        {//it's one of our listens
            integer f = llListFindList(parse(llList2String(buttons,a)),[d]);
            if(f+1)
            {//we matched a button
                string g = llList2String(parse(llList2String(values, a)),f);
                string h = llList2String(parse(llList2String(names, a)),f);
                if(g!="")
                {
                    integer e = llList2Integer(types,a);
                    msglink(llList2Integer(prims,a), llList2Integer(intchans,a),
                            llList2String(answers,a), [g, h, e,
                            llGetInventoryNumber(e), c, b,
                            (llList2Float(times,a) - ticks) * ticksize]);
                    remove(a);
                    cleanup();
                    return;
                }
                else if(h=="+")
                    generate(a,(integer)llList2String(parse(
                            llList2String(values, a)), f - 1) + Buttons - 2);
                else if(h=="-")
                    generate(a,(integer)llList2String(parse(
                            llList2String(values, a)), f + 1) - Buttons + 2);
                else
                    llOwnerSay("Catastrophic failure");
            }
        }
    }
    timer() {
        ++ticks;
        integer a;
        float c;
        key d;
        integer e;
        integer f;
        integer g;
        while(a<llGetListLength(times))
        {
            e = llList2Integer(masks,a);
            c = llList2Float(times,a);
            g = 0;
            if(llGetAgentSize(d = llList2Key(users,a)) == <0.0,0.0,0.0>)
            {
                g = 1;
                if(e&0x004)
                {
                    f = llList2Integer(types,a);
                    msglink(llList2Integer(prims,a), llList2Integer(intchans,a),
                            llList2String(answers,a), [-3, "", f,
                            llGetInventoryNumber(f),
                            d, "", (ticks - c) * ticksize]);
                    jump skip;
                }
            }
            if(c <= ticks)
            {
                g = 1;
                if(e&0x008)
                {
                    f = llList2Integer(types,a);
                    msglink(llList2Integer(prims,a), llList2Integer(intchans,a),
                            llList2String(answers,a), [-4, "", f,
                            llGetInventoryNumber(f),
                            d, "", (ticks - c) * ticksize]);
                }
            }
            @skip;
            if(g)
                remove(a);
            else
                ++a;
        }
        cleanup();
    }
}
ToP

Links

ScriptLibrary
LibraryDialogModule
Comments [Hide comments/form]
Attach a comment to this page: