Jump to content

LepreKhaun

Resident
  • Posts

    1,384
  • Joined

  • Last visited

Everything posted by LepreKhaun

  1. Though it's good to see someone giving credit where credit is due, including my name is inappropriate since I had not published any work along these lines at the time you originally posted this code.
  2. I've given you a Kudo for not only being an excellent problem solver but for posting your solution(s) as you found them for others that might encounter the same at some point. Glad things have worked out for you.
  3. irihapeti wrote: ... I was always accept help and suggestions in the spirit is given OK, here's a suggestion: [Third and final edit] After the protracted conversation that follows, I remove the crossed out suggestion below, since it's obviously flawed. It did, however, lead to some enlightening discussion about probabilities. Maybe some good will come out of that. Since the odds of nine character representations matching anything BUT a specific key is minuscule (it works out to be app. 0.000,000,000,000,000,000,000,008,748 - figuring eight 15 bit possibilities and a ninth of 8 bits, ALL having to match but NOT on a boundary for a "false positive") one just needs llSubStringIndex() By eliminating the spaghetti code in the search, we open up enough room for almost 10 more oranges into the crate. Like so: integer u = -3329; // table uniqueid. can change to whicheverinteger m = 3329; // max number of records. set lower if get stack/heap collisonsstring d; // data tableinteger c; // count of records in tabledefault{ link_message(integer n, integer b, string s, key k) { if (b != u) return; b = 0; if (c < m) { // encode s = llDumpList2String(llParseString2List((string)k, ["-"], []), ""); string e; integer i; for (i = 28; i >= 0; i -= 4) { n = (integer)("0x" + llGetSubString(s, i, i + 3)); b = (b << 1) | (n & 0x1); n = (n >> 1) & 0x7FFF; e += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((n + 0x800) << 12) & 0xF000000) | (((n + 0x0800) << 10) & 0x3F0000) | ((n << 8) & 0x3F00))); } b = (b & 0xFF); e += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((b + 0x800) << 12) & 0xF000000) | (((b + 0x0800) << 10) & 0x3F0000) | ((b << 8) & 0x3F00))); // search if(~llSubStringIndex(d, e)) { //we found it b = 1; } else { // add to data string d += e; b = 2; } } llMessageLinked(LINK_THIS, b, "", k); } } [Edited to replace faulty algorithm for the reason given.]
  4. irihapeti wrote: maybe you could write the wiki entry yourself. Me not being a wiki editor. It would be more useful i think. As more people going to go to the wiki than will ever read this post. It soon be buried and forgotten in a few days. Unlike the wiki + just as a FYI. the very first writing of the encoder was: string eih(integer n, integer i){ string r; while (~--i) { r = llGetSubString("0123456789abcdef", n & 15, n & 15) + r; n = n >> 4; } return r;}// -- encoder ---string eiu(integer n){ n += 0x800; return llUnescapeURL( "%" + eih(0xe0 + (n >> 12), 2) + "%" + eih(0x80 + ((n >> 6) & 0x3f), 2) + "%" + eih(0x80 + (n & 0x3f), 2));} can see for this that is clear what is the significance of 0xE0808000 and how is being used + A very helpful person commented on this codes at the time and said can get a performance gain if rewrite the same as is now. The int2hex is a killer. And I say to them thanks and say thats really good of you to help me like that and I change the codes to that way they didnt think they had anything to prove when they made the suggestion. I accept in the spirit it was given and I was happy to be helped and accepting off it + I was always accept help and suggestions in the spirit is given When modding other peoples' code, it pays to familiarize oneself with what is going on. The significance of 0xE0808000 is in the encoding of an integer to UTF16 which uses an intermediate step using one or more UTF8 encoded bytes. It turns on the required bits so llBase64ToString(llIntegerToBase64()) knows to encode exactly three bytes of the integer (no more, no less) to the resulting U+0800 - U+87FF code point. See http://en.wikipedia.org/wiki/UTF-8#Description for details. I contribute to the wiki at times because I use from it and am able to give back in a meaningful way. However, I fail to see how that addresses the lack of comments in your code that might help someone like revochen Mayne to easier comprehend what you're doing.
  5. Welcome to Secondlife Life- 'Your World within the Rules LL has decided to support today. sorta' kinda'.." The General forum might be a better place for this type of rant, otherwise the readership is going to be limited to those coding rather than simply talking abouit coding...
  6. revochen Mayne wrote: Sorry, wasn't intended as offence. I even love those type of code allthough i rarely understand it yet. ... Perhaps irihapeti would be so kind as to comment her code for the rest of us. Not all of us are familiar with these "<<", "&" and "|" operators or what "0xE08080000" might signify (the wiki doesn't help much!) and an explanation of how you're using them to accomplish what purpose and why would be appropriate here. You could start with "0xE0808000"- what is the significance of it and how is it being used? And then go on to tell us what is happening In the code surrounding it, please.
  7. Role playing within scripted rules becomes fantasy gaming. Thats what you're wanting to do but you've found LSL doesn't allow you to do fantasy gaming to the extent you wish. That's because SL isn't a fantasy gaming platform. I'd recommend trying to implement this idea on Unity within the Steam network. You'd not only have more options available to you that you desire but you'd find a wider audience for that type of fare as well.
  8. I feel as if you're approaching all this backasswards. Take it from the top down: You have individual avatars (all wearing HUDs) that are required to do some tasks to accomplish some goals and these tasks entail some in-world objects. And some of these tasks need other tasks to have been completed before the present task can be done. In other words, one couldn't get the apple from the tree unless they had first gotten a ladder from somewhere else . Right? Now, does the tree need to see if you have a ladder or does the HUD check to see if you have a ladder to climb up to the apple? It can be done either way but let's say there are two types of ladders, one that can be easily found but has a 50-50 chance of breaking and one which never breaks but can only be found if the player has managed to get into the master's locked storage shed. How is the tree to know which type of ladder is being used? Well, the HUD could know because it has kept track of what the player has accomplished earlier. And, yes, this does make the coding of the HUD more complex but consider the alternative: you have to notify the tree which ladder has been found whenever any player finds one and then when the player tries to climb up to the apple, the tree has to tell the HUD what the outcome would be. And if there's only that one tree and you have a hundred players active, which would be the easier solution- one tree trying to keep track of 100 players' ladder inventory or 100 individual HUDs seeing if they have a ladder or not at the time?
  9. Estelle Pienaar wrote: ... If the player clicks on an object, it has to send the HUD at least three pieces of information: (1) the key of the avatar that clicks [so that the HUD knows that not another player clicked the object], (2) The name of the task, (3) the status of a mandatory previous task [as a precondition for accomplishing the actual task]. ... You only have to send number one, the key of the avatar touching it at the moment. Name the object according to the task, it's name is available in the listen event handler. Have the HUD itself keep track of tasks completed.
  10. DannyAeon wrote: ... I was happy to help people in the Mesh creation forum with the things I have learned about mesh creation, but next time I should probably just point someone to the Inworld Employment forum so that they can attract the attention of a 3D modeler for hire. After looking at your posting history and seeing how much you've contributed to the Mesh forum, I can offer you the following: No one has ever learned to either drive nor construct a car by looking at show room models.
  11. This may help you understand what is happening: // get next four nybbles and make integer from them//// 0000 0000 0000 0000 abcd efgh ijkl mnopn = (integer)("0x" + llGetSubString(s, i, i + 3));// copy lowest bit (p), stash in b after shifting b upb = (b << 1) | (n & 0x1);// shift n right 1 place and mask with 32,767//// 0000 0000 0000 0000 0abc defg hijk lmno n = (n >> 1) & 0x7FFF; // OK, here we encode the integer (except for p, which is now stored in "b", which will be encoded at the last) e += llBase64ToString(llIntegerToBase64( // Start with -528,449,536 0xE0808000 |//// 1110 0000 1000 0000 1000 0000 0000 0000 OR// ADD 2048 to n then SHIFT LEFT 12 places AND mask that with 25,165,824(((n + 0x800) << 12) & 0xF00000) |// 0000 0000 0000 0000 0abc defg hijk lmno +// 0000 0000 0000 0000 0000 1000 0000 0000 =// 0000 0000 0000 0000 0abc Defg hijk lmno << 12// 0000 0abc Defg hijk lmno 0000 0000 0000 &// 0000 1111 0000 0000 0000 0000 0000 0000 =//// 0000 0abc 0000 0000 0000 0000 0000 0000 OR // ADD 2048 to n then SHIFT LEFT 10 places AND mask that with 4,128,768(((n + 0x0800) << 10) & 0x3F0000) | // 0000 0000 0000 0000 0abc Defg hijk lmno << 10// 0000 000a bcDe fghi jklm no00 0000 0000 &// 0000 0000 0011 1111 0000 0000 0000 0000 =// 0000 0000 00De fghi 0000 0000 0000 0000 OR// SHIFT LEFT 8 places AND mask that with 16,128((n << 8) & 0x3F00)));// 0000 0000 0000 0000 0abc defg hijk lmno << 8// 0000 0000 0abc defg hijk lmno 0000 0000 &// 0000 0000 0000 0000 0011 1111 0000 0000 =//// 0000 0000 0000 0000 00jk lmno 0000 0000 EQUALS // RESULT HERE ===>>> // 1110 0abc 10De fghi 10jk lmno 0000 0000
  12. irihapeti wrote: ty (: i fixed that one and the mask. well spotted. ty No, you made it worse. e += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((n + 0x800) << 12) & 0xF00000) | (((n + 0x0800) << 10) & 0x3F0000) | (n & 0x3F00))); Should read: e += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((n + 0x800) << 12) & 0xF000000) | (((n + 0x800) << 10) & 0x3F0000) | ((n << 8) & 0x3F00))); Otherwise, the last part is missing the bytes it should be masking. But as I said, this isn't the correct forum to practice in. OK?
  13. irihapeti wrote: edit: i made some mod/opt to the oranges script i put here before. If anybody got that one already then delete and have this one if you want the other post script has a count flow error in it. so best not to use that one at all. bc counts the duplicates as well as the adds. I was testing that and forgot to change before post the main change I made was to the coding style of the search algo. i made all inline style bc is more consistent readability wise than to mix classic and inline coding styles in same code block as i was doing. I think anyways removed a unecessary int var, a else, and a modulus as well // store 3339 encoded keys losslessly// call this script with table id -3339 in num // llMessageLinked(LINK_THIS, -3339, "", yourkey);// return codes in num// 0 = table full// 1 = key found in table // 2 = key added to table // link_message(integer sender_num, integer num, string message, key id)// { llOwnerSay((string)num + " " + (string)id); } // // Public Domain May 2014 by elizabeth (irihapeti)// Base64 codes credit Strife Onizukastring d;integer c;default{ link_message(integer n, integer b, string s, key k) { if (b != -3339) return; b = 0; if (c < 3339) { // encode s = llDumpList2String(llParseString2List((string)k, ["-"], []), ""); string e; integer i; for (i = 28; i >= 0; i -= 4) { n = (integer)("0x" + llGetSubString(s, i, i + 3)); b = (b << 1) | (n & 0x1); n = (n >> 1); e += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((n + 0x800) << 12) & 0xF000000) | (((n + 0x0800) << 10) & 0x3F0000) | (n & 0x3F00))); } e += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((b + 0x800) << 12) & 0xF000000) | (((b + 0x0800) << 10) & 0x3F0000) | (b & 0x3F00))); // search b = 0; i = llSubStringIndex(d, e); if (~i) { n = (i % 9); if (!n) jump y; i += (9 - n); n = llStringLength(d); @x; if (llGetSubString(d, i, i + 8) == e) jump y; if ((i += 9) < n) jump x; } d += e; c++; b++; @y; b++; } llMessageLinked(LINK_THIS, b, "", k); } } I'm unsure why you feel the LSL Scripting Library is a place to practice coding. As it is, in your careless haste to squeeze a few more keys in, you FUBAR'ed Strife's [edited for correctness after being informed they only lent a hand in the script and bits and pieces were written by others] the original code completely. This is your most obvious error. Can you see what you did wrong or shall I explain it to you? e += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((n + 0x800) << 12) & 0xF000000) | (((n + 0x0800) << 10) & 0x3F0000) | (n & 0x3F00))); There's at least two more besides that. Perhaps you'd best stick with modding simpler things until you get the hang of all this.
  14. irihapeti wrote: yw (: is there anything else I can help you with understanding? No, that will do here, you've contributed more than enough as it is. Getting back on topic and summing up: Using my simple, basic database script and it's accompanying test harness, one not only can store over 700 unique keys but also compare different compression algorithms, of which four were suggested, each with a possible use for a specific need. Sassy Romero rightly pointed out that hashes could be used, albeit with a chance of collision (meaning the hash of two or more keys are the same and the risk is both such being used in any given program). This risk may be allowable in some circumstances but the programmer should be aware exactly what the odds are of it failing before going that route. The gains to be achieved with this approach is limited only by the risk of collision one feels they can live with. Dora Gustafson pointed out that using Resident Names not only might require less memory than their UUIDs but there may be circumstances it is preferable. I agree on both counts, especially where any last name of "Resident" may safely be chopped before storage. Unsure what the "average" Resident Name length might be, but watching free memory after each addition in the data store would avoid problems. Then irihapeti suggested the use of a combined work of her(elizabeth), Adam Wozniak, Doran Zemlja, Becky Pippen and Strife Onizuka. This effectively doubled the number of keys that could be stored than my simplistic "drop the hyphens" approach.. Of course, if all one was interested in was stuffing more keys into the box, the optimal approach would be to not to use strings at all. Rotations (quaternions) store 4 float values very efficiently in lists, a UUID can be easily broken into 4 integers and (after much hard work!) Strife Onizuka, Pedro Oval and Omei Qunhua have developed a way to convert between integers and floats. That raises the limit of lossless compression of Keys to above 2,000 within a single script. // "Store 700+ Unique UUIDs In World" by LepreKhaun 4/18/2014// Modified 4/29/2014 to use the "fui" and "iuf" functions // developed by Strife Onizuka, Pedro Oval and Omei Qunhua// from the "Combined Library" found at https://wiki.secondlife.com/wiki/Combined_Library// This version will store ***2,071*** unique UUIDs with the (possibly unneeded) decoder function "fui"//// See http://community.secondlife.com/t5/LSL-Library/Store-700-Unique-UUIDs-In-World/td-p/2669408 for usage// May be freely used, modified and distributed ONLY with this header intact! 2071// NOTE! Always obtain and use the latest version of these functions from// https://wiki.secondlife.com/wiki/User:Strife_Onizuka/Float_Functionsfloat iuf(integer a) {;}integer fui(float a) {;}list keysStored;default{ link_message(integer sender_num, integer num, string str, key id) { if (~num) // abort unless num != -1 return; // delete hyphens from key string str = (string)id; string shortKey = llDumpList2String(llParseStringKeepNulls((str = "") + str, ["-"], []), ""); rotation rotKey = < iuf((integer)("0x" + llGetSubString(shortKey, 0, 7))), iuf((integer)("0x" + llGetSubString(shortKey, 8, 15))), iuf((integer)("0x" + llGetSubString(shortKey, 16, 23))), iuf((integer)("0x" + llGetSubString(shortKey, 24, 31))) > ; // see if the key is in list if(~llListFindList(keysStored, [rotKey])) { // it was found llMessageLinked(LINK_THIS, TRUE, "", id); } else { // it was not found, so // store it first keysStored += rotKey; llMessageLinked(LINK_THIS, FALSE, "", id); } }} But, of course, there is an upper limit to all that. The reader is advised to use a web based data storage solution for anything more than this. Attempting to implement a DBMS (Data Base Management System) in LSL is going to be more complicated than one might realize. And there's no need to try to reinvent the wheel in an unsuitable environment when all one needs to do is learn a bit of PHP, MySQL (which is a simple-to-use-and-learn DBMS loaded with features!) and how the llHTTP* functions work together. I do hope the reader has been able to glean something useful from this topic and I do thank you for reading this far.
  15. irihapeti wrote: i just add to the discussion for people thinking about table/page/script ids in the linked forum post as i mention before is a technique of partitionning integer num into caller/callee pairs the idea being that a called/script can know who has called it. it use the form: num = (callerid << 16) | (calleeid); where caller and callee are uniqueids so caller goes: llLinkMessage(LINK_THIS, (myid << 16) | (calleeid), msg, id) callee goes: link_message(integer sender, integer num, string msg, key id) { if (num & 0xFFFF == myid) // then is for me whocalledme = (num >> 16) & 0xFFFF; + ok can partition this down further. for example if only have 256 scripts in app num = (myid << 8) | calleeid; this allows the top 16 bits for messages as well as string msg in the example encoded key table codes then can mod so tableid is some number less than 0xFF. where 0xFF is reserved for the Manager script if (!(b & 0xFF == myid)) return; whocalled = (num >> 8) & 0xFF; if whocalled is not on my list of valid callers then error do the encoding and search etc then pass message back to caller b = (returncode << 16) | (myid << 8) | whocalled; llLinkMessage(LINK_THIS, b, "", k); caller can then reverse to get the return codes. and can know which table return this result. So Manager can fire off lots of messages/tasks to lots of scripts and know when they complete and what is status of job complete. if fire a task then can know not to fire another task at a script until get message back Absolutely fascinating.
  16. irihapeti wrote: LepreKhaun wrote: irihapeti wrote: i notice in the above header you refer to the encoder as a compression algo is not a compression. is an expansion. the set of all keys can be stored natively in 16 bytes per element. the key as we use/see in LSL is an expansion of this native element to 72 bytes. The encoder algo expands native to 18 bytes so is why is referred to as an encoder in the field of compression bc it it dont actual compress I'm uncertain how the word "compression" translates to your language but I was using it in its computer science definition, as did .Adam Wozniak and Doran Zemlja in their early implementation of this algorithm. Basically, not all encoding is compression but all compression is an encoding, if that makes sense. If your encoding wasn't a compression algorithm, you would've ended up storing the same number or fewer keys in the available memory. And, since more keys are stored and the original keys can be recovered from their compressed state, it is specifically a lossless compression. [ETA] There is an "expansion algorithm" there but that's what you're calling the decoder. It expands 9 UTF-16 characters back into the 32 UTF-16 characters (which are the original hexadecimal characters you compressed in the first place). Got it? i realise that people refer to this kinda algo as compression. Which is understandable when look at it in the most general sense in the field of compression is different classes of algos. compressors, packers and encoders is what I mean when say that this algo is not a compression algo. As it doesnt attempt to reach the entropic state of the ordinal set of inputs by exploiting commonalities that may be found in the inputs. it does the opposite. it dont try to reach the entropic state. it goes in the opposite direction algorithmically by design. Even tho space saving occurs. is a class of algo thingy this which makes sense to people who work in this field + can call this algo a packer tho. I never refer to it as a packer bc is not a very good one as wrote. So just refer to it as a encoder if was writing a packer then can losslessly encode 30 keys in 256 UTF chars. 17.067 bytes per. Instead of 18 bytes per as wrote if was writing a compressor then exploiting commonalities in keys, as well as the above. Order 0, 1, 2, etc + i have never looked closely at avatar keys myself in any exhaustive way, but I read once somewhere that one of the symbols near the middle (dont remember exactly now which one) is typically hex 0xF in many avatar keys. So that could be exploited for some bit savings. like for example if was 0xF 1/2 of the time then can gain approx. 31 bits for every 30 keys win some lose i also read some other time that the last bytes of keys seem to be generated by noise from the system clock in whole or part. Is not confirmed that just seems to be. if so can exploit that as well as a clock has known bounds. So can maybe get some gains in that area as well in a compressor this last two things are Order 0 techniques. If go to Order 1, 2, etc then might identity some other areas of commonality as well. Might maybe + if we ever were allowed access to the codes that LL do use to generate keys then could pretty probably easy compress to under 128bits per. The entropy being the ordinal set of the keys generated to date not that LL will ever ever let us see them codes. bc spoof. SL would get pretty messy for the residents in that situation very interesting.
  17. Sorry, https://wiki.secondlife.com/wiki/Category:LSL_Security is pretty much all we have in LSL.
  18. irihapeti wrote: seeing as how you posting my own codes back at me. I suppose i better do some work now (: have inlined the encoding and put a table full flag in as well can squeeze in 1 or 2 more keys if mod more but i quite like 1661. dunno why just do (: // stores 1661 encoded keys in a table// call this script with table id -1661 in num // llMessageLinked(LINK_THIS, -1661, "", yourkey);// return codes in num// 0 = table full// 1 = key found in table // 2 = key added to table // link_message(integer sender_num, integer num, string message, key id)// { llOwnerSay((string)num + " " + (string)id); } list d;default{ link_message(integer n, integer b, string s, key k) { if (b != -1661) return; b = 0; if (llGetListLength(d) <= 1661) { s = llDumpList2String(llParseString2List((string)k, ["-"], []), ""); string e; integer i; for (i = 28; i >= 0; i -= 4) { n = (integer)("0x" + llGetSubString(s, i, i + 3)); b = (b << 1) | (n & 0x1); n = (n >> 1); e += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((n + 0x800) << 12) & 0xF000000) | (((n + 0x800) << 10) & 0x3F0000) | ((n << 8) & 0x3F00))); } e += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((b + 0x800) << 12) & 0xF000000) | (((b + 0x800) << 10) & 0x3F0000) | ((b << 8) & 0x3F00))); b = !~llListFindList(d, [e]); if (b) d += [e]; b++; } llMessageLinked(LINK_THIS, b, "", k); } } Very interesting.
  19. irihapeti wrote: i notice in the above header you refer to the encoder as a compression algo is not a compression. is an expansion. the set of all keys can be stored natively in 16 bytes per element. the key as we use/see in LSL is an expansion of this native element to 72 bytes. The encoder algo expands native to 18 bytes so is why is referred to as an encoder in the field of compression bc it it dont actual compress I'm uncertain how the word "compression" translates to your language but I was using it in its computer science definition, as did .Adam Wozniak and Doran Zemlja in their early implementation of this algorithm. Basically, not all encoding is compression but all compression is an encoding, if that makes sense. If your encoding wasn't a compression algorithm, you would've ended up storing the same number or fewer keys in the available memory. And, since more keys are stored and the original keys can be recovered from their compressed state, it is specifically a lossless compression. [ETA] There is an "expansion algorithm" there but that's what you're calling the decoder. It expands 9 UTF-16 characters back into the 32 UTF-16 characters (which are the original hexadecimal characters you compressed in the first place). Got it?
  20. If you post your script, we might could tell you what you're doing wrong. Lacking that, very few of us are going to make guesses. [ETA} And if it's not a script that you wrote yourself, contact the person that wrote it, don't post it here. Thank you.
  21. If you post your script, we might could tell you what you're doing wrong. Lacking that, very few of us are going to make guesses.
  22. irihapeti wrote: .. [previous quotes snipped]... +/- for bytecode yes. i did mention that in the line above the codes yes ? + for people who might end up reading this the encoder/decoder linked to was designed to help with answering the questions - how to encode a key losslessly into a smaller space? - how to store encoded keys in logical groupings so that they can be extracted and decoded without loss - how can the storage method be implemented so is transportable to other storage medium? use cases other than OP wanting to transport to scripts and notecards (storage medium) is when transporting to a external website, packing into containers, etc. it only came into this thread when the discussion turn to what other formats can be used to store unique identifiers losslessly in this DB solution the discussion in this subthread is now about formats. Is not about the design of the DB solution itself. Which as I already said is pretty good. The lossy hash version is also pretty good when the probability loss margin is acceptable for your use case + anyone reading the link discussion can see that I actual agree with Jopsy and suggest an alternative coding approach to the problem confronting OP the problem being that OP was trying to jam everything into fewer scripts than the app requirements metrics actual allow. Which OP came to realise themself. So all good + i just make another observation about optimisation in the xorhash version for the readers. bc I am a modder (: if mod/move the hashing algo to the harness side then can pass to DB as integer. Can get a performance gain doing this, and can reduce further the bytecode size of the DB script by some amount. Is a transfer coding technique this. Transfer the bytecode space consumed to another memory block of the app where the space constraints are more relaxed. if also think about this a bit then can see how I would deal with the encoder bytesize issue in any mod I might do in a particular use case it may also be useful to know on the harness side what is the hash of a key for some other purpose. So if modding Leprekhaun's lossy DB solution for own purpose/use case then can think about this as well + in the general case then is not a biggie to not do the kind of opt/mod that I been chatting about !!! and.... important !!! opt/mod can obscure the purpose/intent of a general library solution. The purpose/intent of library is to provide a solution for the general case that can be easy used by others as is within its own bounds, and can be easy modded for specific use cases where those bounds need to be pushed/extended so take what I am chatting about with this in mind ok. me modder No need to get so defensive here. If you're going to make comparisons, you're required to do so in a way that apples are still apples is all. As it turns out, your suggestion is an improvement of 2x. // "Store 700+ Unique UUIDs In World" by LepreKhaun 4/18/2014// Modified 4/27/2014 using the suggestion of// irihapeti to use a complex compression algorithm// as written by elizabeth in http://www.sluniverse.com/php/vb/scripting/93810-quotation-marks-strings.html#post1928288//// This version will store *** 1,487 *** keys//// See http://community.secondlife.com/t5/LSL-Library/Store-700-Unique-UUIDs-In-World/td-p/2669408 for usage// May be freely used, modified and distributed ONLY with this header intact!//// BEGIN example key encoder decoder// public domain April 2014 by elizabeth (irihapeti)// a mod of works by:// Adam Wozniak, Doran Zemlja, Becky Pippen, Strife Onizuka// with mentions for exacts in the codes//// encodes a key (uuid) into a string of 9 UTF16 chars. 18 bytes// str = Key2UTF(key) // key = UTF2Key(str) //// UTF16 codes produced are copypasta into scripts and notecards in // SL viewer 3.7.3 (287491) Mar 4 2014 05:01:31// on Windows 8.1. Default USA english// dunno about earlier/later versions, LSL Editor or TPVs or other OS// just need be careful when copypasta as// - some UTF glyphs are not visible but are in the string// - many of them show as the same glyph. but they are decodeable// so best to Say wrapped in "" for copypasta purposes //// warninkkks !!! is no error trapping !!! if you need that then mod // -- encoder ---integer enB; string enU(integer n){ // credit: Strife return llBase64ToString(llIntegerToBase64( 0xE0808000 | (((n + 0x800) << 12) & 0xF000000) | (((n + 0x800) << 10) & 0x3F0000) | ((n << 8) & 0x3F00)));} string enP(integer n){ enB = (enB << 2) | (n & 0x3); return enU((n >> 2) & 0x7FFF) + enU((n >> 17) & 0x7FFF); } string Key2UTF(key k){ string s = (string)k; string r = enP((integer)("0x" + llGetSubString(s, 28, 35))) + enP((integer)("0x" + llGetSubString(s, 19, 22) + llGetSubString(s, 24, 27))) + enP((integer)("0x" + llGetSubString(s, 9, 12) + llGetSubString(s, 14, 17))) + enP((integer)("0x" + llGetSubString(s, 0, 7))); return r + enU(enB & 0xFF);}// --- end encoder --- // --- decoder ---integer deB;list deH = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]; integer deU(string s){ // credit: Becky s = llEscapeURL(s); return ((((integer)("0x" + llGetSubString(s, 1, 2)) & 0x1F) << 12) | (((integer)("0x" + llGetSubString(s, 4, 5)) & 0x3F) << 6) | ((integer)("0x" + llGetSubString(s, 7, 8)) & 0x3F)) - 0x800;} string deP(string s){ integer n = (deU(llGetSubString(s, 1, 1)) << 17) | (deU(llGetSubString(s, 0, 0)) << 2) | (deB & 0x3); deB = deB >> 2; return llList2String(deH, (n >> 28) & 0xF) + llList2String(deH, (n >> 24) & 0xF) + llList2String(deH, (n >> 20) & 0xF) + llList2String(deH, (n >> 16) & 0xF) + llList2String(deH, (n >> 12) & 0xF) + llList2String(deH, (n >> 8) & 0xF) + llList2String(deH, (n >> 4) & 0xF) + llList2String(deH, n & 0xF);} key UTF2Key(string s){ deB = deU(llGetSubString(s, 8, 8)); return (key)( deP(llGetSubString(s, 6, 7)) + "-" + llInsertString(deP(llGetSubString(s, 4, 5)), 4, "-") + "-" + llInsertString(deP(llGetSubString(s, 2, 3)), 4, "-") + deP(llGetSubString(s, 0, 1)));}// --- end decoder --- list keysStored;default{ link_message(integer sender_num, integer num, string str, key id) { if (~num) // abort unless num != -1 return; string elizabethCode = Key2UTF(id); // see if the key is in list if(~llListFindList(keysStored, [elizabethCode])) { // it was found llMessageLinked(LINK_THIS, TRUE, "", id); } else { // it was not found, so // store it first keysStored += [elizabethCode]; llMessageLinked(LINK_THIS, FALSE, "", id); } }}
  23. irihapeti wrote: 1642 keys for 65520 memory +/- however much bytecode the script uses more/less this than this gen script default{ touch_end(integer total_number) { integer k = 1642; list lst; string s; integer i; integer j; integer n; for (i = 0; i < k; i++) { for (j = 0; j < 9; j++) { n = (integer)llFrand(0x8000); s += llBase64ToString(llIntegerToBase64( 0xE0808000 | (((n + 0x800) << 12) & 0xF000000) | (((n + 0x800) << 10) & 0x3F0000) | ((n << 8) & 0x3F00))); } lst += [s]; s = ""; } llOwnerSay((string)llGetUsedMemory()); }} + a example key encoder/decoder can be found down in this chat for anybody who might want to play with such a thing http://www.sluniverse.com/php/vb/scripting/93810-quotation-marks-strings.html is public domain so can do whatever you want with it as you like + edit: i just correct the range in the gen script to be the same as the encoder script. it bump it up to a little bit to 1692 bc the range i had was overflowing on some randoms injecting extra spurious chars into the stream 1692 is right on the edge so in production codes then should have a way big margin for safety bc the memory allocation for LSL MONO is pretty unreliable seems like Very nice try but you're not working with a single key anywhere in your code, you're just storing 9 integers away in a string. You need the entire suite of subroutines as elizabeth wrote them to handle keys and Jopsy summed up the consequences of this approach quite well imo. And keep in mind that our programs carry memory overhead of it's own, one never has 64K of data storage. default{ state_entry() { llOwnerSay((string)llGetUsedMemory()); }}
  24. irihapeti wrote: according to the wiki entry you linked to below then (in MONO) a 9-char UTF16 string consumes 36 bytes when stored in a list (any length string carries fixed overhead of 18 bytes apparently) . a key as string consumes 90. So 2.5x not 3x by equivalence for the approximation (guesstimate) then 700 x 2.5 = 1,750 The only way I know for you to verify your guess is to spend a few minutes coding your approach.
  25. Gayngel wrote: This script doesn't "force open"the notecard on acceptance. With the setting to open notecards on acceptance as enabled, sometimes during an inventory exchange of multiple items a notecard doesn't automatically open. This script ensures that, it will open. I just don't want it to offer the notecard as a second offer on touch. I have an avatar kit vendor that gives about 30 free items and would like the styling notecard that is included to open automatically. I'll try to make a very complicated answer as simple as possible- You no can do if they don't want to.
×
×
  • Create New...