Jump to content

Grabbing a list of inventories that matches one or more regexes


primerib1
 Share

Recommended Posts

I'm making a "gift giver" that will handout items in its inventory, but not all items; just those that matches one (or more) regexes.

So I made the following:

list EMPL;

DeleteKeys(string pattern) {
    // Try trigger GC
    llSleep(0.01);
    list lsd_keys = llLinksetDataFindKeys(pattern, 0, 0);
    integer idx = -(lsd_keys != EMPL);
    if (idx) do {
        llLinksetDataDelete(llList2String(lsd_keys, idx));
    } while (++idx);
}

BuildGiftSet() {
    // Pre-build cleanup
    DeleteKeys("^_item:");
    DeleteKeys("^_gift:");
    // Try trigger GC
    llSleep(0.01); 

    // First we make a set of all our inventories
    integer j = llGetInventoryNumber(INVENTORY_ALL);
    // llGetInventoryName() does not support negative indexing, so we are forced to use standard for() loop
    integer i;
    for (;i<j;++i) {
        llLinksetDataWrite("_item:" + llGetInventoryName(INVENTORY_ALL, i), ".");
    }

    list gift_keys;
    list regexes_k = llLinksetDataFindKeys("^_regex-");
    i = -(regexes_k != EMPL);
    if (i) do {
        // Grab a regex and use the regex to find matching items
        gift_keys = llLinksetDataFindKeys("^_item:" + llLinksetDataRead(llList2String(regexes_k, i)));
        j = -(gift_keys != EMPL);
        // Record the items. Dupes will get merged
        if (j) do {
            // llGetSubString used to remove the "_item:" prefix
            llLinksetDataWrite("_gift:" + llGetSubString(llList2String(gift_keys, j), 6, -1), ".");
        } while(++j)
    } while (++i)

    // Now the set of gifts are all in LSD, with keys prefixed by "_gift:"
}

// regexes are read from the notecard, they will be saved in LSD like so:
//   "_regex-0": "Gift Item .*"
//   "_regex-1": "Older Gifts .*"
//   "_regex-3": "some_other_regex"
//   "_regex-4": "yet_more_regex"
// The number after the "_regex-" part means nothing; they are just to make unique keys.
// The easiest way is to just use the global var containing the line number to read from the notecard
// Like notice "_regex-2" does not exist because line 2 of the notecard is empty

// To grab the gifts and give it out to someone:

        list gift_keys = llLinksetDataFindKeys("^_gift:", 0, 0);
        integer count = -(gift_keys != EMPL);
        if (!count) {
            llSleep(1);
            llRegionSayTo(toucher, 0, "Giver has nothing to give.\nIf you think this is an error, please inform a manager.");
            return;
        }
        list gifts;
        do {
            gifts += llGetSubString(llList2String(gift_keys, count), 6, -1);
        } while (++count);
        // Define target and folder_name somewhere, of course.
        // You might want to filter the target, e.g. based on active group.
        llGiveInventoryList(target, folder_name, llListSort(gifts, 1, TRUE));

 

Critiques & suggestions welcome!

 

Edited by primerib1
Trigger GC?
Link to comment
Share on other sites

Am I overthinking this? Can't I just simplify things like prefixing items to exclude with, say "~~"?

Why YES of course, to both questions!

I just like seeing how much I can push LSL to do some code acrobatics 😎

Link to comment
Share on other sites

5 hours ago, primerib1 said:

llGetInventoryName() does not support negative indexing, so we are forced to use standard for() loop

~--index doesn't depend on negative indexes, although looping backwards is "interesting" in some cases (not this one I don't think)

Otherwise, interesting strategy. If it were me though, I'd probably write a CSV list of inventory items to the key of the regex that they match. Also at te scale where these sorts of acrobatics become a reasonable thing to do (rather than say, a manually curated list of category+item read from the notecard) the most likely case to handle is one or two items being added or removed from inventory at a time. It'd be better to try and optimize for the differential case rather than building the indexing from scratch after any change.

  • Like 1
Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...