Jump to content

Quistess Alpha

Resident
  • Posts

    3,878
  • Joined

  • Last visited

Everything posted by Quistess Alpha

  1. I've only tried the llSetEnvironmentParams direction, but the SKY_SUN parameter is indeed the position of the sun. You should be able to pull out the azimuth and elevation with something like rotation skySun; vector v = llRot2Fwd(skySun); float azimuth = llAtan2(v.y,v.x); float elevation = -llAtan2(v.z,llVecMag(<v.x,v.y,0>)); // UNTESTED!
  2. I haven't tried it, but my back-of-the envelope calculation says you could fit about 3120 keys if they were compressed using base 95 (20 bytes per key + 1 for an unused value) or ~700 more than Molly's method. If you could get rid of the value, that'd only give you another ~100 keys. theoretically true, but in order to leverage existing base64 functions in LSL in the most obvious way, you have to encode in 32 bit -> 6 character blocks (*4 ints in a key = 24 characters). I might see if I can get the byteshifting to work it down to 20+1.5 next I have some free time though. ETA: Actually I think that's basically what you said in your last sentence after I parsed it a few times...
  3. I'm a little bit confused by your implementation format for LSD. In non-LSD you have uncorrelated lists, in LSD you have group IDs and AV ids grouped in pairs in the LSD? why not just treat AV IDs and Group IDs identically? There's very little chance of a collision Also, I would store the block or allowed in the value of the LSD: // LSD keys of the form "Acc:"+UUID. key avId; key grId; string val; if(val=llLinksetDataRead("Acc:"+avId)) { if("allowed"!=val) { return FALSE; } } if(val=llLinksetDataRead("Acc:"+grId)) { if("allowed"==val); { return TRUE; }else { return FALSE; } } return FALSE; // or so; there are 9 cases to check, and I'm too lazy to set up a truth table for the implementation in the OP.
  4. This is a resident to resident discussion forum, for direct support you'll need to contact Linden Lab with a support ticket here: https://lindenlab.freshdesk.com/support/home Since you're paid premium, they might be able to verify that you are who you say you are with your payment information somehow.
  5. if(!pointer--) { //0 }else if(!pointer--) { //1 }//... else { // was probably -1 all along. } might be more practical.
  6. At the moment I'm using it to define a menu structure, to make my menuing system easier to maintain. Sure, other storage methods are more efficient, but are you really going to remember the exact ordering of a CSV list specification when you want to edit the script a year from now?
  7. string json = "{\"a\":\"a\", \"b\":\"b\"}"; json = llJsonSetValue(json,["c"],JSON_DELETE); llOwnerSay(json); // JSON_INVALID. Attempting to delete a non-existent key in a JSON object deletes the whole JSON object. Expected behavior?
  8. Probably unnecessary unless The ranges are semantically helpful (for example, testing HTTP return codes, grouping 400's together makes sense) Some snippet can be 'factored out' of like categories You have hundreds, not handfuls of tests. (in most cases you're probably doing something wrong if you need that many conditionals) also, for range checks, you only need to check one direction:
  9. Yeah the only real optimization you can do is re-order them so that the "most likely" branches are highest in the list (also a fairly micro-optimization). if your if-conditions and actions have some sort of correspondence, you can sometimes re-organize it into a non-conditional, but that's only possible in specific cases.
  10. Yeah that's my opinion as well. script memory UUIDs are grossly inefficient because utf-16 takes up a constant 2-bytes per character, and I've heard rumors keys also store the numeric value of the UUID as well. utf-8 has neither of those issues, so you're already more than halfing the memory footprint while the key is stored as a string in LinksetData memory. I don't really see a good use-case for saving an extra 16 bytes on top of that, but since I already had a base 92 for positive integers lying around, (landmark coordinates are conveniently always positive) it wasn't too much of a stretch to work out once I wrapped my head around negative numbers. (I kinda wish I had figured out how to overflow just right so decoding didn't have to check the sign of the number, oh well.)
  11. An example of how to convert a key to base 95, which should take up 20 bytes in LinksetData memory:
  12. Dumping these here; more key packing ideas for use in utf-8 (I.E. LinksetData) base 95 was a bit harder than I thought it would be, because I forgot negative numbers are a thing. I've not thoroughly checked edge-cases, nor unwrapped function calls, nor pre-calculated powers of 95. string KeyToB64(string s) { integer a = (integer)("0x"+s); integer b = (integer)("0x"+llGetSubString(s,9,12)+llGetSubString(s,14,17)); integer c = (integer)("0x"+llGetSubString(s,19,22)+llGetSubString(s,24,27)); integer d = (integer)("0x"+llGetSubString(s,-8,-1)); return llDeleteSubString(llIntegerToBase64(a),-2,-1)+ llDeleteSubString(llIntegerToBase64(b),-2,-1)+ llDeleteSubString(llIntegerToBase64(c),-2,-1)+ llDeleteSubString(llIntegerToBase64(d),-2,-1); } key B64ToKey(string s) { return FourInts2Key( llBase64ToInteger(llGetSubString(s, 0, 5)), llBase64ToInteger(llGetSubString(s, 6,11)), llBase64ToInteger(llGetSubString(s,12,17)), llBase64ToInteger(llGetSubString(s,18,23)) ); } string KeyToB95(string s) { integer a = (integer)("0x"+s); integer b = (integer)("0x"+llGetSubString(s,9,12)+llGetSubString(s,14,17)); integer c = (integer)("0x"+llGetSubString(s,19,22)+llGetSubString(s,24,27)); integer d = (integer)("0x"+llGetSubString(s,-8,-1)); return IntegerToB95(a)+ IntegerToB95(b)+ IntegerToB95(c)+ IntegerToB95(d); } key B95ToKey(string s) { return FourInts2Key( B95ToInteger(llGetSubString(s, 0, 4)), B95ToInteger(llGetSubString(s, 5, 9)), B95ToInteger(llGetSubString(s,10,14)), B95ToInteger(llGetSubString(s,15,19)) ); } string IntegerToB95(integer X) { string ret; integer i; // intermediate values. integer delta = 32; if(X<0) delta = 127; // 32+95 X = X-(i=(X/(95*95*95*95)))*95*95*95*95; ret+=llChar(i+delta); //llOwnerSay((string)i); X = X-(i=(X/(95*95*95)))*95*95*95; ret+=llChar(i+delta); //llOwnerSay((string)i); X = X-(i=(X/(95*95)))*95*95; ret+=llChar(i+delta); //llOwnerSay((string)i); X = X-(i=(X/95))*95; ret+=llChar(i+delta)+llChar(X+delta); //llOwnerSay((string)i); return ret; } integer B95ToInteger(string s) { integer delta = 32; if(llOrd(s,0)>=80) delta = 127; // 80 = 32+ 95/2 return (95*95*95*95*(llOrd(s,0)-delta))+ (95*95*95*(llOrd(s,1)-delta))+ (95*95*(llOrd(s,2)-delta))+ (95*(llOrd(s,3)-delta))+ (llOrd(s,4)-delta); } key FourInts2Key(integer a, integer b, integer c, integer d) { // convert to key format. string ret = int2hex(a)+int2hex(b)+int2hex(c)+int2hex(d); ret=llInsertString(ret,20,"-"); ret=llInsertString(ret,16,"-"); ret=llInsertString(ret,12,"-"); ret=llInsertString(ret,8,"-"); return ret; // automatic string to key conversion. } string int2hex(integer i) { // lowercase. replace all 39's with 7's for UPPERCASE. string ret; integer w; w = (i&0x70000000)>>28; w+= 8*(i<0); // correct for LSL 'arithmetic shift'. ret += llChar(0x30+w+39*(w>=10)); w = (i&0x0F000000)>>24; ret += llChar(0x30+w+39*(w>=10)); w = (i&0x00F00000)>>20; ret += llChar(0x30+w+39*(w>=10)); w = (i&0x000F0000)>>16; ret += llChar(0x30+w+39*(w>=10)); w = (i&0x0000F000)>>12; ret += llChar(0x30+w+39*(w>=10)); w = (i&0x00000F00)>>8; ret += llChar(0x30+w+39*(w>=10)); w = (i&0x000000F0)>>4; ret += llChar(0x30+w+39*(w>=10)); w = (i&0x0000000F); ret += llChar(0x30+w+39*(w>=10)); return ret; } default { state_entry() { key k = llGenerateKey(); string b64 = KeyToB64(k); key after = B64ToKey(b64); llOwnerSay(llList2CSV([k,b64,after])); string b95 = KeyToB95(k); after = B95ToKey(b95); llOwnerSay(llList2CSV([k,b95,after])); /* // sanity check for negative numbers. integer rand = (integer)llFrand(1000000000)-2000000000; string b95 = IntegerToB95(rand); integer aft = B95ToInteger(b95); llOwnerSay(llList2CSV([rand,b95,aft])); */ } }
  13. I'm presuming we're not using the 8th bit, because that's reserved for designating multi-byte characters. 7 bits per character -> 16*8/7 =~ 18.25 or 19 characters. If you convert the encoded value of a UUID into base 95 (128 possibilities in 7 bits, less 32 = 96, one fewer for safety) 20 digits gives you a range up to 3584859224085422343574104404449462890625 values, which is just a bit bigger than the 2^128 possible values of a UUID.
  14. No not really. I think the theoretically best method for relative performance testing would be to run both functions simultaneously in separate scripts, for a predefined interval of time (say, 5 seconds) and have them each report the number of repetitions. That's a bit of a hassle to set up properly though.
  15. Just to add to the possible solutions, if the object says anything in local chat, and is not moving, you can touch its name and select "map" from the popup, which should make a red and blue pillar approximately (within 1 meter of) where the object is. It's rather situational though. Also it doesn't work if your avatar is within 1 meter of the object.
  16. I don't believe "elapsed time that was allotted to the script" is something we have access to, which is the problem. maybe someone could file a Jira to extend llScriptProfiler()?
  17. To give the illusion of running thousands of scripts on a region that has a few orders of magnitude fewer processors, scripts are constantly stopped from running to give time for all the other scripts in the region time to run. the time it takes from when your script is stopped to when it starts running again after everyone else has had their turn is (I believe/assume) about 0.02 seconds, which is why llGLL reports roughly 0.02, 0.04 or 0.06 seconds, and not 0.01, 0.03 or 0.05. I've not considered or tried using llGetTimestamp() to measure small intervals so I can't comment on it being more or less accurate.
  18. For what it's worth, you can use llResetTime() or even llGetAndResetTime() to save the 2 variable overhead, at the expense of hypothetically messing with another portion of your script somewhere that depends on llGetTime();
  19. IIRC mono is abysmal at creating lists from scratch. try (some_list != NULL_LIST) where NULL_LIST=[] is a global variable.
  20. For what it's worth, sending a message directly to the avatar is often a nice/(The only? IIRC llGetAttachmentList doesn't return HUDs) way to discover the existence of a HUD they're wearing. After you've grabbed the key, you can switch to direct communication with the HUD itself. Tangentially relevant, if you get a response from a HUD and want to know the avatar, llGetOwnerKey(listen_ID_parameter); is very handy in these sorts of systems. Since avatars own themselves, it can even be used to differentiate HUDs/avatars and is safe to use without checking whether the ID is a HUD first .
  21. Products like that generally use an animation to move the avatar's visual position very far underground, and for good measure, have them adopt the fetal position or such-like to take up less space.
  22. RLV isn't suitable for most tasks you'd want a bot to do. here's the manual: https://wiki.secondlife.com/wiki/LSL_Protocol/RestrainedLoveAPI for a bot, you'd probably specifically want to ~not use a normal collar to prevent people who aren't you from abusing your bot. Cool VL Viewer has a lua API which can make it do most bot-things. here's that manual sldev.free.fr/CoolVLViewerLuaManual.pdf (may be slow to load if you're in the US) Radegast is also a good viewer for bot stuff I've heard, but it's hard to find their documentation. p.s. I peeked at Corrade's documentation just for fun, and the formatting on that website is actively nauseating. Who thought an animated background behind script snippets was a good idea? </rant>
  23. you're not putting the variable into the function, you're putting in the string "test" which is not valid JSON. llOwnerSay(llJsonGetValue(test,["playlists",0,"id"])); // no quotes.
×
×
  • Create New...