Jump to content

LepreKhaun

Resident
  • Posts

    1,384
  • Joined

  • Last visited

Everything posted by LepreKhaun

  1. LepreKhaun

    Events

    If you're certain everything is set properly but still have this problem, I'd suggest filing a support ticket (which may be more effective if done by the land owner themself) on it to have the matter looked into. There may be something server side that needs attending to and, if so, it won't get fixed unless they know about it. And the person handling the issue may find that something was, after all, overlooked. Either way, that should clear this up for you. {ETA: See Opening a support case at http://community.secondlife.com/t5/English-Knowledge-Base/How-to-contact-customer-support/ta-p/739385 if you're unsure how to do that. Hope that helps!]
  2. There's two approaches to both the design and generation of complete Json texts, top down and bottom up. Usually one will end up doing a bit of both along the way, but designing from the top down and generating the text from the bottom up is usually easiest. Let me show you what I mean. Using the example Json text from my last posting we'll first examine it from the top down { "KeyZ": [ [], [ "Boo!", null ] ], "KeyB": 3.141500, "KeyH": { "B": true, "hi!": { "KeyZ": 230045 } }} We start with the left most Values, which are the ones "highest" in the tree and examine them first. As you go to the right, you go "deeper" or "lower" into the tree. So, at the topmost level, the root, we have a Json object, shown by the curly braces all the way to the right. At the second level, we see the three Keys, "KeyZ", "KeyB" and "KeyH". We can take them in any order but we'll consider them as we come down the page, since this will also be the order that the arrays will have and order is important with them. "KeyZ" has an array Value whose first Value is another array, which is empty. The second Value of KeyZ's array is an array which has two Values within it, "Boo!" and then 'null'. And that's pretty much it for "KeyZ" so we go on to "KeyB" which has the Value of 3.141500. But notice those extra zeros that the Json generator tacked onto the end: That always happens with float values (including the floats within vaectors and rotations), 6 places to the right of the decimal, either padded with zeros or (careful now!) cut short, truncated, at that point. So, if you require greater precision than that, convert your your floats into strings before encoding them to Json text. It just won't be recognized as a JSON_NUMBER later is all. OK? Moving on to "KeyH", we see that its Value is an object with two Keys within it. The first is "B" and its Value is the bare word 'true' and the other Key "hi!" has an object Value with one Key:Value pair within it. So, how does one make this? From the bottom up! In other words, we go backwards through our top down examination and we'll make the Value for "hi!" first, like so: // this gives us the Json text string '{"KeyZ":230045}'string hi = llList2Json(JSON_OBJECT, ["KeyZ", 23005]); Next we want to encode that as the Value of "hi!" with "B" and its Value, 'true': // this gives us the Json text string '{"B":true,"hi!":{"KeyZ":230045}}'string keyH = llList2Json(JSON_OBJECT, ["B", JSON_TRUE, "hi!", hi]); Now "KeyH" has two siblings and one is straightforward so we have to deal with the other, with its lower levels, before we can put them all together. And, looking at our Pretty Print we can see the next thing we should do is the array holding "Boo!" and 'null'. And that array is a sibling of an empty array, both of which are within an array. Right? So let's do this in one swell foop: // this gives us the Json text string '[[],["Boo!",null]]'hi = llList2Json(JSON_ARRAY, [llList2Json(JSON_ARRAY, []), llList2Json(JSON_ARRAY, ["Boo!", JSON_NULL])]); Take a second to understand what we just did and note how the empty array in the first position was generated. Because now we have all that's needed to finish this Json text. // Note the strided list of ["Key", Value] pairs here at this levelstring jsonText = llList2Json(JSON_OBJECT, ["KeyZ", hi, "KeyB", 3.1415, "KeyH", keyH]); And there you have it: jsonText => '{"KeyZ":[[],["Boo!",null]],"KeyB":3.141500,"KeyH":{"B":true,"hi!":{"KeyZ":230045}}}' Some of you might realize that all that could've been done without the string variables 'hi' and 'keyH' by substituting the llList2Json() functions that initialized them right into place within that last step: // Errrr, maybe that's a bit too much of a shortcut, ehstring jsonText = llList2Json(JSON_OBJECT, ["KeyZ", llList2Json(JSON_ARRAY, [llList2Json(JSON_ARRAY, []), llList2Json(JSON_ARRAY, ["Boo!", JSON_NULL])]), "KeyB", 3.1415, "KeyH", llList2Json(JSON_OBJECT, ["B", JSON_TRUE, "hi!", llList2Json(JSON_OBJECT, ["KeyZ", 23005])])]); So, you also have Dora's elegant solution to look over (thank you, Dora, you're always so helpful!). Hopefully you might have gained enough of an understanding of all this to appreciate how the use of a Json object can be so much more powerful than our piddling lists and when an array may be more appropriate than an object to use. And I can assure you that the material on the wiki and other documentation will improve, Xiija. Just keep in mind that this is a very recent addition to our tool belts and it'll take a bit to get right. And let's not forget that these functions aren't completely shaken out yet and LSL does have lousy string handling (anyone that has had the convenience of working with the 'char' value type knows how crippled LSL is in this department). Oh, and it should be pointed out that these Json handling functions are slowwwwww. I mean 15 to 20 times slower than comparable list operations. So, don't try using these in time critical applications unless you take that into account. As for this rambling "lecture" of mine, I don't feel it's too shabby for a first draft and (thank you, Rolig and Peter!) has gotten some constructive feedback on how it can be improved. Any other ideas or suggestions are welcome, as with any questions on any points you need clarified. Anywho, that's a wrap for me for now. Off to get drunk...
  3. Thank you, that's an excellent beginners intro to all this. I'll keep that in mind
  4. OK already! Here we go with some of the worst LSL art you'll ever see. Don't say I didn't warn you- I really, really, really can't draw! But I got to thinking about your advice, Rolig, and you're usually spot on about such things. And I could certainly see the need for these in a "Json for Dummies" book. I just felt that since I was replying to a person who, in your own words, "is a programmer who already knows what JSON is and why you might want to use it", I'd just cut to the chase, so to speak. Anyway, here's my lousy attempt to illustrate my boring, windy lecture on a complicated subject for the rest of you. First off, we'll look at the root nodes of a Json array and an object. Not too much to see there but I'll point out they're both enclosed within double quotes because they are, at the root level, LSL strings after all. You can tell them apart because the array uses square brackets and the object uses curly braces. However, they're both empty, which is allowable, but not too instructive. Keeping in mind that the empty list is used to access the root: llJsonValueType(jsonText, []); would return JSON_ARRAY or JSON_OBJECT accordingly. Now we'll look at an array with some Values in it. In fact, this one has 3 values in it and they are Ordered, meaning they're accessed by Index and their position in the array is important, same as a LSL list. The index starts at zero and ends at length-1. Another way of saying the same thing is that the root array has three children and they are all leaf nodes (meaning none of them have child nodes of their own). So: llJsonValueType(jsonText, []); would return still return JSON_ARRAY llJsonValueType(jsonText, [0]); would return the Value Type found in the first position and llJsonValueType(jsonText, [2]); would return the Value Type found in the last position and llJsonValueType(jsonText, ['anything else but 1']); would return JSON_INVALID The Json text for this array looks like this: "[Value,Value,Value]" and if I "pretty printed" it (meaning breaking it open to see the structure better): [ Value, Value, Value] (Note the commas between the Values, just as with a LSL list.) Moving on to a Json text object with 3 Values in it as well. You should notice that these are Unordered, meaning it doesn't matter where they are in the group. That's because these are accessed by "Key", their name, which is always going to be a string, always will appear in the Json text within double quotes, always have a colon after them and after that colon should always have a Value following (even if it's just 'null'). And these "Key":Value pairs are separated by commas as well. So this object could look like "{"KeyZ":ValueZ,"KeyB":ValueB,"KeyH":ValueH}" or "{"KeyH":ValueH,"KeyZ":ValueZ,"KeyB":ValueB}" (remember, the order doesn't matter within an object but notice how the associated Value stays with its "Key"). and: llJsonValueType(jsonText, []); would return return JSON_OBJECT llJsonValueType(jsonText, ["KeyH"]); would return the Type for ValueH which is associated with "KeyH" and llJsonValueType(jsonText, ["KeyZ"]); would return the Type for ValueZ which is associated with "KeyZ" and llJsonValueType(jsonText, ['anything else but "KeyB"']); would return JSON_INVALID Pretty printed it might appear as: { "KeyB": ValueB, "KeyH": ValueH, "KeyZ": ValueZ} OK, one more bad picture and I won't strain your eyes any more. This one is titled "Nesting!" because, well, that's what it's attempting to show you visually. I ask you to study it for a few minutes now. See what you can make of it from what we've discussed so far. Can you identify the Value within each node? Can you see which are the leaf nodes? Can you see the parent-child relationships? Do you see any significance to that red line as it's drawn? [HINT: It's visiting each of the leaf nodes only once.] I've placed some commas around at places, they're not really part of the tree structure, they're more like training wheels to aid you in seeing what the Json text would look like. Can you work it out? Here's the Json text that's represented in the picture: "{"KeyZ":[[],["Boo!",null]],"KeyB":3.1415,"KeyH":{"B":true,"hi!":{"KeyZ":230045}}}" Pretty Printed using https://wiki.secondlife.com/wiki/User:LepreKhaun_Resident/Json_Pretty_Printer (feel free to use that in any of your development efforts btw): Oh, and refer back to that red line I had scribbled in and see how it relates to the structure in Pretty Print form... { "KeyZ": [ [], [ "Boo!", null ] ], "KeyB": 3.141500, "KeyH": { "B": true, "hi!": { "KeyZ": 230045 } }} It's left as an exercize for the reader though to determine the pathToValue (I mean "specifiers"!!! Linden Lab named that list "specifiers" and that's the name we should use!) used to access any of these values and here's the hand coded LSL string (which initially requires those "leaning toothpicks" to get the double quotes within the string) that you can use to play around with- "{\"KeyZ\":[[],[\"Boo!\",null]],\"KeyB\":3.1415,\"KeyH\":{\"B\":true,\"hi!\":{\"KeyZ\":230045}}}" Next and final Part will be the last, for sure!
  5. LSL gives us two Json generator functions; llList2Json() and llJsonSetValue(). The first creates Json text "from scratch" using a LSL list and the second allows one to change and insert Values (in a somewhat limited way, I'll get to that) into existing Json text. One can also hand code Json text, but it's highly recommended to use the LSL functions to do this to avoid making noncompliant Json text that may bedevil you later. But, before getting into the functions, let me point out exactly what a 'Json text' is. A Json text is defined as a LSL string that is either a Json array or a Json object. If it's not either of those, it's just a string in LSL and, within a Json text, it's a Json Value (which might become a Json text itself when extracted). In other words, if an LSL string doesn't have the form of "[ ... ]" or "{ ... }" it is NOT a Json text, it's simply a string. Now, first we'll consider llList2Json() (https://wiki.secondlife.com/wiki/LlList2Json ). This creates Json arrays or objects from LSL lists. A Json array results from using JSON_ARRAY as it's first parameter, an empty list will result in an empty array ("[]", which is perfectly valid) and everything within the list will be converted in a way that only strings can be later retrieved. If one desires a Json object, you'll use the JSON_OBJECT flag as it's first parameter. Empty objects ("{}") result from empty lists and they also are allowed. Nonempty lists used for Json objects MUST be formed from 2-strided lists where the first and every other element is a string, which will become the "Key" for the following Value. Care should be made that each "Key" is unique and not reused within an object. Otherwise, only the last such "Key" within the object will be directly accessible. I repeat, be careful to ensure the uniqueness of your "Key" within each object. You can and most likely will reuse the same "Key" in other objects but that's as it should be. They each will have their own, unique pathToValue (is it just me or does that term make more sense than "specifiers"?). OK, so now you've made a Json text, an object or an array. Big whoop, eh. But, this is where the power of Json comes into it: You can now take that Json text and use it as a Value within another object or array! And, when you do so, you have "nesting" and can start to build as complex of a data structure as you dream of. Arrays within arrays, objects within objects, an array as the Value of one Key and an object as the Value of the next. And all of you that have tried to juggle three or more lists to keep them in sync should see the beauty of that. If not, wait for my fifth and final posting... Now we'll discuss llJsonSetValue() (https://wiki.secondlife.com/wiki/LlJsonSetValue ). This is a useful tool that has a number of uses; changing a Value within a Json text, appending a Value to an array and adding a new "Key":Value pair to an object. I'll cover each of these in turn. The main thing to keep in mind throughout is that the third parameter, the new Value, must be a string, there is no implicit type casting here as you get from within a list using llList2Json(). If you need to update a Value with a new one, you just address the Value you wish to update using them good ol' "specifiers". The third parameter you've supplied will overwrite that location. A few things should be pointed out: Numbers (both integers and floats) must be entered as LSL strings but will result in a JSON_NUMBER (in other words, without quotes within the Json text). If you actually need a string containing a number, you need to 'double quote' them, as in "\"18\"" (note the back slash escapes being used). Regarding arrays; negative indexing, where the count works back from the end of a list, doesn't work here. And an "out of range" index (which will be defined in a moment) will result a return of JSON_INVALID. Otherwise, to change the Value of a "Key" within an object, you'd use (say) 'string newJson = llList2Json(oldJson, ["Tom", 5, "Jill"], "18");' [ETA: Oops!] 'oldJson = llJsonSetValue(oldJson, ["Tom", 5, "Jill"], "18");' which would result in "Jill" now having the Value of '18'. There's two ways to add to the end of a Json array (unfortunately, no way to directly insert a Value at a location though). One way, when you don't know the number of Values within it is to use JSON_APPEND at the end of the "specifiers" list. The JSON_APPEND flag is actually the integer value of '-1' and that can be used as well, keeping in mind that it doesn't point to the last item in a list but to position one past the end of an array. Also, if one knows the length of the array, you can use that. In other words, given an array of '["A", "B", "C", "D"]', I could add "E" to it by using the "specifiers" list of [JSON_APPEND] or [-1] or [4] and each of those would result in '["A", "B", "C", "D", "E"]'. HOWEVER, and this is important, if I tried to lengthen the array by using [5] or any greater number, the array would be destroyed and a JSON_INVALID would be returned (however, the JSON_INVALID return only happens at the topmost level currently, which is what the Jira in my first posting was about). So, it's best to get in the habit of always using JSON_APPEND (or -1 if you have CTS). Using an out of range specifier can cause a great deal of unneeded hardship. To add a new "Key":Value pair to a Json object, you just add the "Key" to the end of the "specifiers" and put its Value as the third parameter to llJsonSetValue(), the same as you would to set a value to an existing "Key". Doing so will create the new "Key":Value pair within the Json text, just like it had been there all along. And there's no danger of duplicating a "Key" within that object either, if it already exists its Value will simply be overwritten. Well, that's pretty much it for generating Json text. Except for a few warnings: First off, never use a number to index an object or a "Key" to access an array. Either JSON_INVALID will result or (maybe worse) your array will be silently replaced by an object or vice versa. Use some care here, especially with JSON_APPEND, it's never to be used on a Json object. OK? Now, about LSL strings in general, there is a minor problem. See, LSL doesn't have the concept of "raw strings" (http://en.wikipedia.org/wiki/String_literal#Raw_strings ). Those are strings that are taken at face value and not "goofed up" by having the underlying language trying to interpret it some way or do a "favor" for you. And LSL can do a number of things to "goof up" strings, probably because it's basically a chat client at heart and never intended its strings to be (say) printed to a document. I haven't fully explored all the caveats with strings, but here are a few worth mentioning, perhaps some of you are aware of more that could be added: In LSL strings, the back slash '\' is used as an escape character. For instance, if you wanted a string to be 'He said "Come back home soon!".', you'd need to write it as "He said \"Come back home soon!\"." No problem really, as long as that period is there between the last escaped quote and closing quote. Without it, things go south very quickly- it silently disappears, leaving a noncompliant empty spot in that place. And the same will happen if you attempt to set a value with a string with a quote at the beginning of it, as in "\"Come back home soon!\" she said."- silently POOF! There are Jiras about this misbehavior (BUG-2954 and BUG-2736) and workarounds are possible but until LL gets it right (and we all should have a good idea when that'll be!), all one can do is be wary of such traps. And what about the back slash itself within a string? Forget about it! Trying to encode a single '\' ends up escaping the following character and if you need to encode a string such as "2\t2", you end up with "2 2" (the \t is being converted to a tab) and so you figure you'll escape the escape character and try to write it as "2\\t2". Nope, that won't work either, you'll end up with "2\\t2" within your Json text. grrrrr! But don't get me started. There's actually very few of these bugs like this and you're not likely to encounter them. So, the bugs you might encounter are really far and few between. And you're unlikely to meet up with them unless you get into all this in a big way and, even then, some are more specific to web/client communication, where you're not generating the Json texts you have to deal with. And there are workarounds for them until they do get fixed. I just needed to touch on these unlikely occurrences so you'd be prepared if you do run into "odd" behavior. Usually such can be fixed with proper coding. Part 5 will wrap it all up. I'd like to thank those of you that have been so patient up until now.
  6. Steph, I should point out that your state timerCount; within the timer event is not doing anything. See https://wiki.secondlife.com/wiki/State state target; for details but, basically, state entry() will NOT be triggered. So you may want a changed() event handler within that state as well.
  7. LSL has three library functions to parse Json text; llJsonValueType(), llJsonGetValue() and llJson2List(). I'll deal with them in that order and will only cover what may be unclear on their wiki pages. The first, llJsonValueType() (https://wiki.secondlife.com/wiki/LlJsonValueType ) is used to determine "what is it?" in a specific location within a Json text. It's return string is one of the Json Flags as I gave in my last posting as well as in the table on its wiki page. It's used mainly for incoming messages that the program will respond according to what it finds. Otherwise, if the program itself generated the text, it should "know" what is where, just as it would "know" that the first value in its list is an integer and not a vector. It might be noted that one of the possible return flags is JSON_INVALID. This is returned when the parser doesn't recognize what's there as a valid Json Value or the location doesn't exist (as given in the "specifiers" *kof-kof-gag*). This is also true of the next function I'll cover. Next, we have llJsonGetValue() (https://wiki.secondlife.com/wiki/LlJsonGetValue ) which is used to extract a Value from the Json text as a LSL string. Three of these Values will be converted, the same as when they are encoded. These are 'null' and the 2 Json Booleans. That is to say, when you encode JSON_TRUE, it will appear within the Json text as the bare word 'true' (bare meaning unquoted). But when you extract it with llJsonGetValue() it'll come out as the Unicode JASON_TRUE string. This function will mostly be used to access leaf node Values within the Json text. For instance, to pull up the rez day of a friend you might access your database like so: ' string rezDay = llJsonGetValue (peopleIKnowDB, ["Friends", "Tasha", "rezday"]);'. Or, used to get the third item of your shopping list like so: ' string toBuy = llJsonGetValue (myShoppingListDB, ["Must_haves", 2]);'. But it might also be used to extract a Json array or object, which brings us to- The function llJson2List() (https://wiki.secondlife.com/wiki/LlJson2List ) converts Json arrays and objects into LSL lists. Arrays are pretty straightforward, They're simply inflated (expanded or exploded) into a list, each Value separated by a comma. However objects inflate into a strided list that has a stride of 2. This strided list consists of the "Key":Value pairs that made up the object. To handle both of these, it might be necessary to brush up on working with LSL lists (https://wiki.secondlife.com/wiki/Category:LSL_List ). Fortunately, LSL does have a lot of library and user functions to handle lists, so at this point you're almost set. Now, all that is good so far, but there's an additional complication here- "nesting". Remember, any of those Values in either an array or an object can also be another array or object. Not to despair though, one simply extracts them from the list and feeds them, one at a time, back into llJson2List(). Wash, rinse and repeat until you are finally down to leaf nodes, the bottom of the rabbit hole. In Part 4, I'll explain generating or encoding Json text and then, finally, give some advice on how to design and debug a complex data structure of your own (which, hopefully, will answer the OP's original question).
  8. Though a Json text in LSL is just merely a string, it is one that is constructed with a set of rules called the JSON Grammar (see http://www.json.org/ and http://tools.ietf.org/html/rfc4627 for details). This grammar recognizes certain Value Types that differ from the LSL types (https://wiki.secondlife.com/wiki/LSL_Types) you've been working with and it'll pay to become familiar with them and the differences. We've already touched on two Value Types, the Json array and object, and I'll include them in the list of the others here. In this list I'll also have the Json Flag associated with the type as well as some notes pointing out similarities and differrences I've found with the LSL types. The Json Flags given in that list are unreadable Unicode symbols btw. So, when checking a value within Json text using llJsonValueType(), one must have a comparison block of 'if else' tests to determine the value if you want to output anything senseable. There is also one other Flag not given there, JSON_INVALID. This isn't a value type but represents something that isn't reconized as a valid Json Type and is also returned attempting an operation on Json text and things didn't go too well. Array - JSON_ARRAY - which is comparable to an LSL List Object - JSON_OBJECT - known as an associative array, record, map, symbol table or dictionary, the closest we have in LSL is a list with a stride of 2 the Boolean constants 'true' and 'false' - JSON_TRUE and JSON_FALSE - which are "really" Booleans, unlike LSL TRUE and FALSE, which are, when one gets down to it, just overloaded integers the constant 'null' - JSON_NULL - representing an empty, valueless placeholder Number - JSON_NUMBER - which include both the LSL integer and float types (but not Inf and NaN) String - JSON_STRING - which is nearly identical to the LSL string It should be noted that the LSL value types Key, Rotation, and Vector are not in that list and are represented in Json text as strings. They are automatically and implicitly converted to strings when in a list using llList2Json() but must be explicitly converted before using them in llJsonSetValue(), as in '(string)<1.0, 1.0, 1.0>'. Also, all values retreived from Json text with llJsonGetValue() are returned as LSL string values and must be explicitly converted as needed (except for LSL keys). In other words, retrieving the value of '3' requires it to be typecast to an integer before using it as such (see https://wiki.secondlife.com/wiki/Typecast for details). Part 3 follows shortly and, as always, questions or comments about this or anything else I may have covered previously are welcomed.
  9. Good point, thank you. Since I can't draw for squat, an excellent illustration of tree structures, as well as some more text explanations for those that might need them is at http://en.wikipedia.org/wiki/Tree_structure and (a bit more complicated) http://en.wikipedia.org/wiki/Tree_(data_structure). However, it is necessary for an understanding of the tree hierarchy for one to grasp what is entailed in nesting lists. Json text can represent some extremely complex data structures and the tree concept is the only way to go.
  10. I agree about the documentation being a bit lacking. Json is a recent addition to LSL though and that should improve in time. The current implementation is also a tad buggy still, which lead me to make the initial posting. But I've found it to be a useful addition regardless and have explored it enough to perhaps help a bit. First of all, the use of "specifiers" is (to me) one of the most poorly named variables I've encountered. I mean, it gives no idea of what it's about and is simply too generic (all variables could be named "specifier", since that what variables do, right?). A much more apt name would be "pathToValue" because Json text is similar to your computer's directory structure, where to find a file within it, you have to know its directory path to get to it. There are really only two main differences between Json text and your computer directory structure: 1) Instead of writing the path as: 'Desktop/Media/CoolPic.jpg', the Json "specifiers" is a LSL list: '["Desktop", "Media", "CoolPic.jpg"]' 2) Json also has "directories" similar to our lists, where one uses a number (called an Index) to access the elements instead of a name (called a 'Key'). So, a pathToValue could be written as '["Desktop", 4, "MyPics", 7, "CoolPic.jpg"]'. So, JSON has two directory-like Values: The Json array, which is very similar to the LSL list- it holds other values within it that are accessed by a zero-based Index. And, like lists, they're enclosed in square brackets, commas separate the Values and an empty array is allowed. So, an array could be '["value1", "value2", 3]'. To retrieve "value1", you'd use the pathToValue of '[0]' and '[1]' would access the second. Unlike LSL lists though, arrays can "nest"- they can have other arrays within them. More about that in a bit. The Json object is very similar to the computer directories you're familiar with, but written in a specific way and with no "soft linking" allowed. These directory-like values are enclosed in curly braces, contain "Key":Value pairs (where "Key" must always be a Json String) that are comma separated and an empty object is allowed. NOTE: These Keys should be unique and used only once within each Json object. So, a Json object could be '{"KeyA":"someValue", "KeyB":3.1415, "Boogie":3}'. The order of these "Key":Value pairs is unimpotant since you retrieve the Values by name (the "Key"), the same as you get a file from your computer. So, the pathToValue '["Boogie"]' would result in accessing the value '3'. These also can be nested and both arrays and objects can contain each other, leading to a tree structure, which is just geek talk for data that has "levels". Now, consider a LSL list structure. It is a collection of values arranged in a line- it has a start, an end, a length and it's a straight shot through it. But a list within a list complicates things a bit. Instead of a straight shot to the end, we might encounter another list along the way which also has its values arranged in a line and we want to keep them separate. Right? So, to do this, we assign them to a "deeper level" than the list its within. And if that second list also contains a list, that third list would be another level "deeper" still. Follow? To represent this concept of levels we picture a tree, with a root that branches out at each level until it finally arrives at its leaves (this tree is in Australia btw, where the "root" is at the top of it). And we use the word "node" to describe the parts of this tree structure. A This data tree (ETA: there are other data tree structure types, we'll consider only that which is specific to Json text here) will always have one root node, as many leaf nodes as it needs and only one, unique path through its branches to get from the root to any of its leaves. And each branching along the way is also a node. If your eyes are starting to glass over, consider your computer directories. Your 'C://' drive would be called the root node, 'CoolPic.jpg' would one of many leaf nodes and to get from the root node to that specific leaf, you'd have to traverse (go through) a path of directory nodes and each of those directories could've been branching to other places at each level. OK, each node within the tree has a relationship with the others. All nodes but the root have one (and only one) parent node (remember, no "soft links" here!), the node directly above it. And all nodes but the leaves have one or more child nodes, the nodes directly below them. Sibling nodes are nodes that share the same parent and are on the same level with each other and an ancestor node is any node higher up the path to the root and includes the root node, which is ancestor to all the nodes within the tree. So, picture the family tree of an amoeba back to a single ancestor. Now some of the families named their children "Joe", "Mike" or whatever, they would be Json object families. Some of them, however, didn't bother with that and decided that simply numbering the children '0', '1', '2', ... was all that was needed and they are the Json array families. So, to write the path to any specific amoeba from that ancestor (the root) in this family tree, at some levels you'd write out the child's name and otherwise you'd use the number of the child in the order of appearance. In other words, to access the "Joe" value, you might have a pathToValue ("specifiers", ugh!) of '[3, "Mike", "Jimmy", 75, "Joe"]'. Where "Joe" is the child of the 76th child of "Jimmy", who was the child of "Mike" who was the 4th child of the first amoeba, "Adam Blob". Anyway, I hope that clears up what the "specifiers" are. It's just a list that is a pathToValue and the empty list '[]' accesses the root of the Json text, which is, if you haven't guessed, the Json text in its entirety. That is to say, if you copy 'C://' drive to a USB disk, you're copying the entire directory structure over because 'C://' is the name of the root of the directory tree. Each additional value in that list goes one step deeper in the tree structure and every Value within the Json text has it's own, unique list to access it. Json Explained Part 2 follows in a bit. Feel free to ask any questions in the meantime...
  11. Just a friendly heads up about a recently filed Jira (that was quickly acknowledged, thank you, Maestro!). Copy & pasted from BUG-3692 so others will be aware of the problem and take precautions before it's fixed. RFC 4627 Non-Compliance by llJsonSetValue() with out-of-range Indices The library function llJsonSetValue() can generate JSON text that does not conform to the JSON grammar as defined in RFC 4627 ( http://tools.ietf.org/html/rfc4627 ). This silently happens when using out-of-range array indices in other than the first of the list specifiers Illustrative Examples: string jT1 = "[1, 2]"; // A JSON array llJsonSetValue(jT1,[2],"t")=>[1,2,"t"] (Expected, same as using JSON_APPEND) llJsonSetValue(jT1,[3],"t")=>JSON_INVALID (Expected, specifier out of range) llJsonSetValue(jT1,[0, 0],"t")=>[["t"],2] (Expected, all specifiers in range) llJsonSetValue(jT1,[0, 0, 2, "t", 75],"t")=> [[],2] (Compliant, HOWEVER may be unexpected???) llJsonSetValue(jT1,[0, 1],"t")=>[,2] (Non-compliant with only first specifier within range) llJsonSetValue(jT1,[0, 1, 2, "t", 75],"t")=>[,2] (Non-compliant, as above): string jT2 = "[ [\"A\", \"B\", \"C\"], 2]"; // Nested JSON arrays llJsonSetValue(jT2,[0, 3],"t")=>[["A","B","C","t"],2] (Expected) llJsonSetValue(jT2,[0, 4],"t")=>[,2] (Non-compliant, as above) llJsonSetValue(jT2,[0, 1, 0],"t")=>[["A",["t"],"C"],2] (Expected, all specifiers in range) llJsonSetValue(jT2,[0, 1, 1],"t")=>[["A",,"C"],2] (Non-compliant, but with the first 2 specifiers both in range) string jT3 = "{\"1\":2}"; // A JSON object llJsonSetValue(jT3,["1"],"t")=>{"1":"t"} (Expected) llJsonSetValue(jT3,["1",0],"t")=>{"1":["t"]} (Expected) llJsonSetValue(jT3,["1",1],"t")=>{"1":} (Non-compliant, with out-of-range index specifier)These strings are non-compliant in that "empty" values are contrary to RFC 4625 2.1.. The LSL parsers- llJsonValueType, llJsonGetValue and llJson2List- return JSON_NULL in those undefined positions but in a very deceptive way: The first two library functions fail to ever return JSON_INVALID, regardless of the length of the specifiers list that initially addresses that location in the JSON text. In other words: string jGood = "[null, 2]"; // OR "[JSON_NULL, 2]", A correct JSON array llJsonValueType(jGood, [0])=>JSON_NULL (Expected, that is what's there) llJsonValueType(jGood, [0, 0])=>JSON_INVALID (Expected, no value at specifiers' location) string jBad = "[, 2]"; // A non-compliant string llJsonValueType(jBad,[0])=>JSON_NULL Though undefined, might be better as JSON_INVALID llJsonValueType(jBad,[0, 0, 2, "t", 75])=>JSON_NULL Deceptive, should definitely be JSON_INVALID llJsonGetValue(jBad,[0, 0, 2, "t", 75])=>JSON_NULL Deceptive, should definitely be JSON_INVALID In other words, if you're currently using llJsonSetValue(), double check your Json array indices to ensure that they are in range. Otherwise, an error condition silently occurs that may lead to prolonged head scratching later. Hope this posting helps someone avoid that.
  12. Though it has been a wished-for capability for quite some time, notecards cannot have clickable web links. The best one can do is to give the URL and ask the reader to copy & paste it into their browser or chat bar (where it'll become clickable once chatted).
  13. After studying quaternions a bit more, I had the face palming moment of realization that they can be used as operators on vectors. With that and a reconsideration of your "is he left of this plane and right of that plane" approach- Here's a simple solution that covers a "tilted" box as well as one that's merely rotated around the Z axis! // Returns TRUE or FALSEinteger avatarIsWithinBox (vector avatarPosition, vector boxPosition, vector boxSize, rotation boxRotation) { // This determines the "centered" and "unrotated" placement of the box sides vector boxSides = boxSize/2; // This "centers" and then "unrotates" the position of the avatar in relationship with the box vector rotAdjustment = (avatarPosition - boxPosition)/boxRotation; // This then does the 6 required "left of/right of" comparisons return (rotAdjustment.x<boxSides.x && rotAdjustment.x>-boxSides.x && rotAdjustment.y<boxSides.y && rotAdjustment.y>-boxSides.y && rotAdjustment.z<boxSides.z && rotAdjustment.z>-boxSides.z ); } Apologies to all I may have bored, confused and/or befuddled as I worked this out. [Minor, nit-picky camel-case edit and another for a scrolling issue.]
  14. Corsica is one of the mainland continents (middle top in this picture) and covers quite a few regions.
  15. Gayngel wrote: Hi all, I bought a modifiable tip jar and would like to script it so that : 1. It has a minimum payment but is open for users to pay what they choose above the minimum. 2. Be able to distribute a percentage of the spoils to myself and a partner. I tried to follow the wiki for Tipjar Spoils notecard but I keep getting a syntax error and the rest of the code is complex. The script that came with the jar which I modified is below. Note I used PAY_HIDE until I can set a default minimum. integer totaldonated;string owner;default{ on_rez( integer sparam ) { llResetScript(); } state_entry() { owner = llKey2Name( llGetOwner() ); llSetText( owner + "'s Tip Jar.\n Minimum of L$100 payable.\n$L0 Donated so far",<.25,1,.65>,1);llSetPayPrice(PAY_HIDE, [100,150,200,250]); } money(key id, integer amount) { totaldonated += amount; llSetText( owner + "'s Tip Jar.\nMinimum of L$100 payable!\n$L" + (string)amount + " Was donated last!\n" + "$L" + (string)totaldonated + " Donated so far",<.25,1,.65>,1); llInstantMessage(id,"Thank You So Much."); llInstantMessage(llGetOwner(),(string)llKey2Name(id)+" donated $" + (string)amount); }} Appreciate the help. Yes, anything from the Wizardry and Steamworks (https://wiki.secondlife.com/wiki/Category:Wizardry_and_Steamworks) group is going to be a bit complex. :matte-motes-dont-cry: Look at the example given at https://wiki.secondlife.com/wiki/LlSetPayPrice , which details how money can be refunded. For a minimum donation, you'd change the line "if(amount != price)" to "if(amount < price)". Other than that, you need to do the debit permissions check and all as they give it.
  16. You'll need to manually clear your chat logs on your local hard drive (from http://community.secondlife.com/t5/English-Knowledge-Base/Text-chat-and-instant-messages/ta-p/700155): Log files Log files are saved to a location that depends on you operating system: Windows XP: C:\Documents and Settings\Username\Application Data\SecondLife\Avatarname\chat.txt Windows 7 and Vista: C:\Users\Username\AppData\Roaming\SecondLife\chat.txt Mac OSX: Users/Username/Library/Application Support/SecondLife/Avatarname/chat.txt Where Username is your system account name and Avatarname is your Second Life username. Important: You may need to enable your file browser's ability to view hidden files to access your chat logs at their default location.
  17. Welcome to Second Life! And, no, SL isn't a game- it's the optimal meta-game and you can make it whatever you wish. No one can be "killed" here, unless they choose to "die" in the course of role playing. Best way to learn about it all is to interact with the other residents. Most will be quite helpful and willing to get you started. Take it slow at first though, there's a *LOT* to learn!
  18. PeterCanessa Oh wrote: Which would, however, mean that I had nothing from which to return, rendering the whole exercise invalid. I had assumed that you were referring to the "single entry, single exit" rule of structured methods (for all: this says there shouldn't be multiple 'return' statements scattered all over the place because it confuses the flow of the programme and makes it less readable/maintainable). In fact, I'd go as far as saying that inlining (duplicated) functions is never a structured approach - the whole point of structured programming being to enforce structure for maintainability, even at the expense of efficiency (which is the point of inlining). I believe you missed my point. Taking unduplicated code into a subroutine adds to the complexity of the code structure. Modularity does have its place. But, yes, I would've written your example with one return statement at the expense of an extra variable, just to keep it properly structured. The same as I would avoid the use of a "jump" within a function that made an extraneous return from the middle of it needed.
  19. All future updates to JsonPrettyChat.lsl, as well as the latest version of this utility, are to be be found at https://wiki.secondlife.com/wiki/User:LepreKhaun_Resident/Json_Pretty_Printer .
  20. PeterCanessa Oh wrote: Yes, style is very subjective. I was, in fact, expecting someone to point out that IF using multiple return statements was a good way to do things in my example (the alternative, more structured, approach being to assign the return value to a single local variable that is then returned when the function ends) then all my 'else if's are redundant. In the case of that example IF the test evaluates as true the function will hit a return and terminate early, so it could only get to an 'else' if the test had failed. As such, vanilla 'if's would be more efficient in this case. Actually, the "more structured" approach would be to inline the unnecessary function you have in your example, which would make the "else if" construction preferable.
  21. steph Arnott wrote: OK, i just used that. Assumed it was LL, but i take your word for it. There are two LSL style guides available to us, Steph, but both are user-written (I'd be surprised to hear that the Linden's cared one way or the other how we wrote our code*); https://wiki.secondlife.com/wiki/LSL_Style_Guide and a more comprehensive one at http://lslwiki.net/lslwiki/wakka.php?wakka=styleguide. If you follow the guidelines set out in at least the first of those, you shouldn't run afoul of anyone's definition of style. But, then again, correct code is the only matter of importance. It doesn't matter how well named one's variables, how strictly you've indented every code block or how well you've followed your choice of case naming- if it doesn't compile, doesn't accomplish the specified task and fails to handle possible input correctly, it's "bad" code in the truest sense. But even "bad" code shouldn't be corrected within a wiki User Page imo. There is a discussion/talk for every page in the wiki (accessible by tab at the top or a "Display comments/form" link at the bottom) that such errors can be pointed out to the user, leaving them to correct or ignore as they choose. Of course, that doesn't apply to the main body of the wiki, the pages not within someone's name space. Even picayune details such as spelling and grammar should be corrected (with such edits flagged as "minor"). And "bad" code examples, though rare in the wiki, should be corrected as soon as they're found. It is our wiki and will be only as good we make it. * A possible exception would be in writing a Jira to report a bug. A Linden could expect at least proper indentation in your example and might complain if it lacked that.
  22. I understand your problem and its frustrations. I hope you all the best in dealing with the issue.
  23. My take on it would be: Report the incidents, let LL investigate to determine how the griefing is being accomplished and let them take whatever steps is required to stop it. I can think of two other techniques that might give the same results as you describe. However, I wouldn't share them in a public forum since I'd feel I'd be making some griefer's job easier. Discussion of security exploits, loopholes and workarounds (whether griefer based, copy bot oriented or account threatening) are best left for the Jira imo.
  24. msw Tomorrow wrote: Not looking for a free script... what a rude a... http://community.secondlife.com/t5/LSL-Scripting/Script-to-remotely-launch-another-script/td-p/2135257
×
×
  • Create New...