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.
The request and return data are specialy formated. There are two functions used to send and interpret the data
Paste these directly into your code for quick setup.
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");
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
//
// 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();
}
}