Jump to content

elleevelyn

Resident
  • Posts

    611
  • Joined

  • Last visited

Everything posted by elleevelyn

  1. I have a but that we we can scrape info on other people's stuff with a script is an argument in favour of deny bot. We don't need a bot to do the scraping as you point out
  2. there are some things that do need a bot as there is no other way to do it. Some are: Invite a person to a closed group (closed groups are typical in group rentals). New LSL function: llGroupInvite() would help with htis with moderating group chat. the bot is mostly picking off the low hanging fruit. Like spammers that embed web phishing links into the chat. [ Edit for clarity. This is/was a bot war. Spammer bots vs Group Moderator bots) A war that Group Moderators (both bot and human) have largely won due to the fairly quick response by Linden Support when spambots are reported)] another use for a group bot is to auto-assign group roles. And to dispense gifts/stuff to group members based on their roles: Gold Member, Silver, Bronze, etc. Again new LSL functions needed: llGroupAddToRole() and llGroupRemoveFromRole() another is setting parcel details. There is no llSetParcelDetails() function. This just came up again earlier in the Scripting forum. The question: How can I limit the number of parcel visitors to 25 at any one time? Answer: have to use a bot there are no doubt other things that do require a bot, just that these 3 come up a lot
  3. yes. This is the thing raised earlier by Paul and others. The change means that we now have to pay more than our Premium cost to host our bot i probably shouldn't but am start to imagine a new Premium benefit for no extra charge. A car park for our one bot in the Great Linden Bot Park. Like endless rows and rows of them all parked up waiting to be called into life
  4. yes that works also i have seen some relatively sophisticated companions enabled/driven by the main account user, using RLV
  5. responding to the use cases raised Bot Group Manager groups are grid-wide. A group management bot doesn't have to be hosted on the Bellisseria estate Bot Companion there is nothing preventing us from creating companions now. We just can't deploy them in Bellisseria when the companion is registered as a scripted agent which raise a question. When is a companion a bot requiring scripted agent status? like if we log in our alt (regardless of viewer type, custom-made or otherwise) and sit them on our boat with us, is our alt a bot ? If we log in 4 alts to do group photography, are they bots ? I would argue not, as they are extensions of ourself for the purpose of our current logged in activity Bot Decorator to decorate a parcel in an automated way then we can script this already (rezzer box). We don't need a bot to do this for us. Need meaning need because there is no other way to do this. Need also not meaning I would like to or I want to personally tho, I would love to have a machine intelligence-driven builder bot. At this time I would have to make it myself and if I did then Linden does allow me to deploy such a builder bot in SL. Just not in Bellisseria. Which is not all that much of an impost due to rez box
  6. a thing that puzzles me is what is the purpose of hosting a bot in/on a Bellisseria Linden Homes parcel, given that commercial activity is not allowed on the estate or more directly, what are the non-commercial uses for a bot in Bellissaria which can't be met by a standard account viewer?
  7. ooowah! 20,000 prims on the region approx 5,000 packed UUIDs in the LSD = 20,000 * 5,000 = 100,000,000 UUIDs and then we have script memory storage as well. We can stuff about 3,000 packed UUIDs into a script and still be able to manipulate it without a stack collision. And we can stuff an unlimited number of scripts into a prim say a 100 scripts in each prim so hopefully the whole thing will still run 100 * 3,000 = 300,000 times 20,000 prims = 6,000,000,000 so altogether 6,100,000,000 UUIDs and after scrolling thru them all, I probably go: How come they don't have any textures that I like. This is sooo sucky! I dunno why I bought this
  8. a place to hunt for neko gestures is at the freebie shops. Most of the larger freebie shops have boxes and boxes full of stuff from the olden days when just about every fifth avatar was was wearing kitty ears and a tail at the freebie shops you hunting for boxes that are titled "Gestures" or something similar. Some boxes have dozens and dozens of gestures in them. Have to wade thru them all tho, to keep the ones that you like. Also too many gestures in the freebie boxes are modify permissions so you can edit them. Which is a quick way into learning how to make your own
  9. i think that the legitimate uses of roaming bots is to fill in gaps that Linden don't yet have a solution for for example: a roaming bot that gathers location info on security orbs and transmits this info to grid travelers (boaties, pilots, drivers, etc) using a bot to gather this info is the only way to do this at this time, whereas the better solution would be for Linden to provide this info on the mini-map. This means that scripts containing llEject and llTeleportHome would need to have some metadata attached to the script so that the region server could more simply advise the client minimap of this another legitimate use of a roaming bot is gridsurvey. A better solution for this I think is for Linden to provide this info directly themselves. In the interests of monetization, Linden could charge a fee to access this service there may be another legitimate use for a roaming bot but I am unsure what that might be. Altho it could be attachment scraping to provide merchant customers with anonymized data on attachment types. Like on this day: Body A 40% usage, Body B 12%, Body C 5% etc. Again tho Linden could itself provide this kind of anonymized data to merchant customers for a fee
  10. WARNING! All Intruders into my parcel space will be surveiled if you do not leave within 60 seconds. After which time I will exercise my parcel space domain rights to inspect the contents of your bag attachment points, just in case you might of pinched something !!!
  11. the tellings the relatively easy part. Building the machine that makes the stuff is relatively quite a bit harder, even when the story has been told exactly to the machine already. A prim-to-mesh convertor for example - compositing only the surface triangles of a linked prim object. Is doable to make such a machine but is not easy. When it is done tho and the source code can be seen then it becomes another of the yeah I knew that moments
  12. for a virtual world a AI Builder could turn out to be quite a blessing for the greatest number of people we could just tell the AI what we want and it makes the stuff for us. And while it is making the stuff then we can interact with it to make changes Like: AI please make me a red summer dress for the body I am wearing, knee length, with a high bodice line and thin shoulder straps so AI makes it then we can say raise the hem a little bit please. And it does that Then we say cool thanks! I would like sandals as well please. Cork soles with white leather straps and a gold buckle other AI interaction AI could you make a 3 room cottage in the West Devonshire style please to fit on a 24 by 24 footprint. Front and left side entrances please then voila! is made. AI move the cottage to the center of the parcel please. Ok cool. ooh! move it to the right a little please. Thanks! thats great AI could you make a little beach please on the west side of the parcel sort of in a stony style. And a forest like path from the beach to the cottage. And then a English style wild garden to the left of the path and like a little forest on the right and some deer and rabbits in the forest visible from the path. Then voila! is all done and on and on. Like: AI please make this rock I am standing on a little bit bigger. Thanks! a thing about this AI is that in the context of a virtual world, we often hear that content is king. More correctly content creation is king. A AI that can create content via conversation enables a whole lot more people to realise their own creative imagination also in this context this AI is more a MI, meaning Machine Intelligence. A machine that is a tool able to interact with human beings on a conversational level even with this capability some people are still not going to do this (spend the time to tell an MI what they want) and will continue to get stuff from other people. What form would the stuff take? I think that over time high-level creatives would/will write conversations and sell them (sell the conversations). A conversation (a story) that the MI can read and act on
  13. i put this here as when we start getting into packing keys then we sometimes start thinking about packing other types like integer, float, vector, rotation; given that when we cast these to string then the result can at times be verbose which can be problematic when we wanting to stuff as much info into the LSD as possible. The merits of stuffing the LSD or otherwise in this way notwithstanding // Base126 Integer to UTF-8 packer // allows char(0x1) as delimiter appended external to this function // return string can be stuffed into LSD and retrieved // variable length: min = 1 max = 5 // // public domain (March 2023) string Int2LSD(integer n) { // encode low to high integer sign = n < 0; // when negative flip bits so -1 -2 .. use same space as +1 +2 .. if (sign) n = n ^ 0xFFFFFFFF; // encode sign and log2(63) value bits into 1st char // log2(63) so 1st char cannot be char(0 or 1) string result = llChar(((n % 63 + 1) << 1) + sign); n /= 63; // encode remainder log2(126) + 2 so chars cannot be char(0 or 1); while (n) { result += llChar(n % 126 + 2); n /= 126; } return result; } integer LSD2Int(string s) { // decode high to low integer result; integer i = llStringLength(s) - 1; for (i; i; --i) result = result * 126 + (llOrd(s, i) - 2); i = llOrd(s, 0); result = result * 63 + ((i >> 1) - 1); if (i & 1) result = result ^ 0xFFFFFFFF; return result; } /* note: at this time (March 2023) optimal size packing of the set of all floats uses the functions: fui() and iuf() https://wiki.secondlife.com/wiki/Combined_Library string packed = Int2LSD(fui(afloat)); float unpacked = iuf(LSD2Int(packed)); from here we can build up to packing vectors and rotations */ default { state_entry() { llOwnerSay("..."); integer v = -3; //integer v = 0x80000000; //integer v = 0x7FFFFFF8; integer n; for (n = v; n < v + 7; ++n) { string e = Int2LSD(n); integer d = LSD2Int(e); llOwnerSay("n: " + (string)n + " d: " + (string)d + " e: " + e + " len: " + (string)llStringLength(e)); } } }
  14. yes agree. When we talking about efficiency/optimisation then it depends on what we are optimising for. In general there are tradeoffs in memory used vs execution time. And as you experiencing there can be low memory used execution time vs high memory used execution time
  15. back in the day when Key2UTF was being developed there was discussion over the street about this, and from what you report is still the case. So is good to know when we get into performance optimisation about llChar vs llList2String. llChar is a relatively slow function generally from what little testing I have done llChar has about 40-50% the performance of llList2String in the inline Int2Hex case llChar((48 + ((buffer >> 28) & 15) + ((buffer > 9) * 39)); llList2String(hex, (buffer >> 28) & 15); I may be wrong about the exact performance ratio tho, so am happy to be corrected
  16. i just add on here that is possible to write a variable length packer such that max. length is 19 and min. length is 1. It uses a different more complex algorithm than above. i am not sure tho the extra time to execute would be worth it, given that the large majority of the set of all keys would still be in the 19 and 18 length category i might have a go at it if I get a time, but I think would be more about curious than anything
  17. a variable length key packer where max. length is 19 and min. length is 16. Is not compatible with the above fixed length packer /* pack/unpack a key into a variable length string of UTF-8 symbols Max length 19. Min length 16 as wrote it uses base127 so best used in the single key case the carry is encoded such that any trailing 'zero' symbols are removed credit: Mollymews/irihapeti for the carry and fast int2hex methods public domain (March 2023) */ string Key2Lsd(string k) { // encode high to low string result; integer carry; integer sign; // strip dash chars k = llDumpList2String(llParseString2List(k, ["-"], []), ""); // encode symbols. loop 4 times: 128 bits / 32 bits = 4 integer i; for (i; i < 25; i += 8) { // read 8 hex symbols into 32-bit buffer // strip off the sign bit and save (negative division coding is unnecessarily complex) integer buffer = (integer)("0x" + llGetSubString(k, i, i + 7)); sign = (sign << 1) + ((buffer >> 31) & 1); buffer = buffer & 0x7FFFFFFF; // encode remainder 31 bits integer j; for (j; j < 4; ++j) { // undecodable value 0x0 // leaves 127 encodable values // shift base127 into base128 symbol result += llChar(buffer % 127 + 1); buffer /= 127; } // carry is max. base9 carry = carry * 9 + buffer; } // encode carry carry = (carry << 4) + sign; while (carry) { result += llChar(carry % 127 + 1); carry /= 127; } return result; } key Lsd2Key(string s) { // decode low to high // note: decoder ignores the 20th symbol (0x1) when appended integer dash = 0x3C; // note: list lookup is the fastest way to do Int2Hex list hex = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]; string result; integer carry; integer sign; // decode carry and sign integer i = llStringLength(s) - 1; for (i; i > 15; --i) carry = carry * 127 + (llOrd(s, i) - 1); sign = carry & 15; carry = carry >> 4; // decode symbols for (i = 12; i >= 0; i -= 4) { integer buffer = carry % 9; carry /= 9; integer j; for (j = i + 3; j >= i; --j) buffer = buffer * 127 + (llOrd(s, j) - 1); // restore sign bit to buffer buffer = buffer | ((sign & 1) << 31); sign = sign >> 1; // buffer to hex symbols string h; if (dash & 1) h = "-"; dash = dash >> 1; h += llList2String(hex, (buffer >> 28) & 15) + llList2String(hex, (buffer >> 24) & 15) + llList2String(hex, (buffer >> 20) & 15) + llList2String(hex, (buffer >> 16) & 15); if (dash & 1) h += "-"; dash = dash >> 1; h += llList2String(hex, (buffer >> 12) & 15) + llList2String(hex, (buffer >> 8) & 15) + llList2String(hex, (buffer >> 4) & 15) + llList2String(hex, buffer & 15); result = h + result; } return (key)result; } default { state_entry() { //key k = NULL_KEY; key k = llGenerateKey(); string e = Key2Lsd(k); string d = Lsd2Key(e); llOwnerSay("\nk: " + (string)k + "\nd: " + (string)d + "\ne: " + e + " len: " + (string)llStringLength(e)); } }
  18. I notice Linden fixed the LSD UTF-8 to UTF-16 bug. Is best to not use code from this post going forward the updated 19-char version is posted in Script Library \ Key2LSD packer/umpacker (optimal size 19 UTF-8 chars)
  19. I noticed (March 2023) that Linden fixed the LSD UTF-8 to UTF-16 bug. So I rewrote Key2LSD and place it here in a post of its own. Is a bit more efficient than the previous bug-workround version /* pack/unpack a key into 19 UTF-8 symbols as wrote it allows char(0x1) to be optionally appended for 20 symbols appending 0x1 prevents cross-boundary collisions when searching a string of packed keys credit: Mollymews/irihapeti for the carry and fast int2hex methods public domain (March 2023) */ string Key2LSD(string k, integer delimit) { // encode high to low string result; integer carry; integer sign; // strip dash chars k = llDumpList2String(llParseString2List(k, ["-"], []), ""); // encode symbols. loop 4 times: 128 bits / 32 bits = 4 integer i; for (i; i < 25; i += 8) { // read 8 hex symbols into 32-bit buffer // strip off the sign bit and save (negative division coding is unnecessarily complex) integer buffer = (integer)("0x" + llGetSubString(k, i, i + 7)); sign = (sign << 1) + ((buffer >> 31) & 1); buffer = buffer & 0x7FFFFFFF; // encode remainder 31 bits integer j; for (j; j < 4; ++j) { // undecodable value 0x0 // allow 0x1 as a optional delimiter // leaves 126 encodable values // shift base126 into base128 symbol result += llChar(buffer % 126 + 2); buffer /= 126; } // carry is max. base9 carry = carry * 9 + buffer; } // encode carry // 4 * log2(9) + 4 (high bits) = 16.68 bits carry = (carry << 4) + sign; for (i = 0; i < 3; ++i) { result += llChar(carry % 126 + 2); carry /= 126; } // append delimiter when requested if (delimit) result += llChar(0x1); return result; } key LSD2Key(string s) { // decode low to high // note: decoder ignores the 20th symbol (0x1) when appended integer dash = 0x3C; // note: list lookup is the fastest way to do Int2Hex list hex = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]; string result; integer carry; integer sign; // decode carry and sign integer i; for (i = 18; i > 15; --i) carry = carry * 126 + (llOrd(s, i) - 2); sign = carry & 15; carry = carry >> 4; // decode symbols for (i = 12; i >= 0; i -= 4) { integer buffer = carry % 9; carry /= 9; integer j; for (j = i + 3; j >= i; --j) buffer = buffer * 126 + (llOrd(s, j) - 2); // restore sign bit to buffer buffer = buffer | ((sign & 1) << 31); sign = sign >> 1; // buffer to hex symbols string h; if (dash & 1) h = "-"; dash = dash >> 1; h += llList2String(hex, (buffer >> 28) & 15) + llList2String(hex, (buffer >> 24) & 15) + llList2String(hex, (buffer >> 20) & 15) + llList2String(hex, (buffer >> 16) & 15); if (dash & 1) h += "-"; dash = dash >> 1; h += llList2String(hex, (buffer >> 12) & 15) + llList2String(hex, (buffer >> 8) & 15) + llList2String(hex, (buffer >> 4) & 15) + llList2String(hex, buffer & 15); result = h + result; } return (key)result; } default { state_entry() { key k = llGenerateKey(); string e = Key2LSD(k, FALSE); // no delimiter string t = Key2LSD(k, TRUE); // delimited with 0x1 string d = LSD2Key(t); llOwnerSay("\nk: " + (string)k + "\nd: " + (string)d + "\ne: " + e + " len: " + (string)llStringLength(e) + "\nt: " + t + " len: " + (string)llStringLength(t)); } }
  20. yes that's a issue with brokers a broker-less multi-vendors - multi-scripts - multi-script-internal processes scheme which produces unique codes less in length than (string)key from the rule that scripts in object Contents must be uniquely named. A unique code can be obtained from linknumber + scriptname + counter example: Say script has same inventory name "A", then when dropped into the object with 3 links and 3 scripts in each link for 9 independent processes then prefixes: "0A", "0A 1", "0A 2", "1A", "1A 1", "1A 2", "2A", "2A 1", "2A 2" naming convention is scripts to be named with an alphabet char in the 1st position. The underscore char "_" reserved and must be coded internally as the prefix delimiter. Creating the prefix code, a one time occurrence in state_entry, edit [dynamically in changed event] each script can then manage its own sub-code scheme as it prefers. Examples: "0A 1_" + "P1" + (string)counter "0A 1_ + "P2" + (string)counter "1A 2_ + "0" + (string)counter "1A 2_ + "1" + (string)counter "2A_" + (string)counter where "PI", "P2", "0", "1" is a sub-process code internal to the script. In the "2A_" case there is no sub-process code (script only having 1 process) bit size of counter is up to the scripter, beyond 32 bits then a multiple integer type counter
  21. a way to do the multiple processes case is with a broker script that manages the allocation of unique key/codes. Each client process requests a block of codes for its own use. When the block is exhausted then either roll over the block or request a new block from the broker the number of processes and size of the assigned block can be quite large for example: integer 32 bits: 1st 8 bits is the unique process prefix: 256 processes and 2*24 unique codes for each process. Key = (string)Prefix + (string)blockcounter the bit split can be other. Like 7 bits for 128 processes. 9 bits for 512 processes with the block size adjusting accordingly scaling up to a 2 integer broker then it can be 2^32 processes each with a 2^32 block. Or 2^16 processes, 2^48 block. etc edit add. The 2 integer method is the simplest as the broker need only assign the process a unique integer identifier. The process managing its own 32 bit counter
  22. i have been following along your posts about your app is unclear to me why you are not using ordinal order to construct unique identifiers. eg. getNext(0) getNext(1) ... getNext(MAX) , getNext(0), ... MAX = 2^32 is a lot of unique keys until the counter rolls over. If need more that this, the getNext counter can use 2 or more integer types we can use a feistel network algo to change the ordinal order arrangement so getNext returns a random-looking unigue value but I don't see any gain for the performance hit
  23. you might be right about this. If I get a bit of time I might have a go at measuring the offerings to date
  24. i am not giving enough explanation, so I do so now in the context of packed keys. The purpose of packed keys storage in a greeter is so that during a period we will only greet a person one time. Person comes to our location, we greet them (typically the greet is some combination of greet message, give LM, invite to group, external website link, etc) the number of keys we can store determines the upper limit of the period Sam visits first time. Greeter: if (key not found in storage) {Welcome Sam! Save key to storage} Sam changes name to Sammy. Greeter: if (key found in storage) {Do nothing as Sammy has the same key as Sam and the key is already in storage} the next time Sam/Sammy is greeted as Sammy is when the next/new period begins. At start of new period Sam/Sammy is not in storage leveling this up. to what you have mentioned send a greetings message every time (Welcome! Sam then Welcome back! Sammy (as you mention), then only drop LMs, group invites, etc one time during the period is the dropping of LMs, etc that greeters typically also do that I didn't explain well when we are ok with dropping on our visitor every time they visit then is no need to pack and store keys
×
×
  • Create New...