$nav ===== Key type ===== The $ty[key] type is similar to the $lty[string] type, in that it can also hold any string. However, it is meant to hold strings that have the format of an Universally Unique Identifier (UUID). The format of an UUID is: * 8 hexadecimal characters. * A dash. * Three groups of 4 hexadecimal characters, separated by dashes. * A dash. * 12 hexadecimal characters. For example, **5748decc-f629-461c-9a36-a35a221fe21f** is the UUID for $lct[TEXTURE_BLANK]. The hexadecimal characters are output in lower case by all functions that output them (such as $lfn[llGenerateKey]), and are accepted in either case by all functions that accept them (such as $lfn[llGetAgentInfo]). There is a special UUID, the null UUID. Its value is **00000000-0000-0000-0000-000000000000**. Some functions that return a key variable may return a null UUID when it's not possible to retrieve the requested one for any reason. For example, $lfn[llGetLinkKey] will return the null UUID if the link number is not valid. There is a constant with the string that corresponds to the null UUID, called $lct[NULL_KEY]. Note that since the $ty[key] type can hold any string, it can be (and has been) (ab)used to fulfil the same role as a $ty[string] (for example, in $lev[link_message] events). === Automatic type conversion between key and string === Type conversion between $ty[string] and $ty[key] happens automatically in most cases. One exception is the string concatenation operator (+). When concatenating a key to a string, the key has to be typecast to string first by prefixing it with ''(string)''. See examples below. There is no syntax to specify a key-typed literal; keys need to be type cast from string by using the ''(key)'' prefix. Even the predefined $lct[] that hold UUIDs are not of type ''key'', but ''string''. This is mostly relevant when storing keys in a $lty[list], because the elements need the correct type when used with functions such as $lfn[llListFindList] or $lfn[llGetListEntryType]. In particular, this bars the possibility of initializing a list with a key literal in the globals section of a script, because type casts are not allowed there. The only possibility to include a key element inside a list in the globals section is to define a key-typed variable first and use it in the list. See examples below. === Additional notes === By using ''if (value)...'', where the type of ''value'' is $ty[key], it's possible to check if a key variable is actually a valid UUID or not. The code in the true branch will execute only when it represents a //valid// UUID other than the null UUID. It only works that way for the $lkw[if] statement and others that accept conditions ($lkw[while], $lkw[do-while], $lkw[for]). In contrast, the expression ''value != NULL_KEY'' will //also// be $lct[TRUE] for every value that is not a valid UUID. See examples below. When comparing two key typed values, they are compared as strings. An implication is that if they differ only in case, even when they represent the same UUID, they won't be considered equal. The //Mono// virtual machine stores extra data in key-typed variables that helps the interpreter run faster, at the cost of script memory. This means that key variables take more space than string variables. Most avatar UUIDs follow the [[http://tools.ietf.org/html/rfc4122#section-4.1.3|version 4 UUID]] format (that is, the first digit of the second four-digit group is a 4, and the first digit of the third four-digit group is either 8, 9, a, or b). However, some very old avatar UUIDs (2002 and early 2003, for example Governor Linden) didn't follow this convention. ===== Examples of automatic type conversion ===== $lfn[llGetOwner] returns a key, and $lfn[llOwnerSay] expects a string. The following examples illustrate how automatic conversion from ''key'' to ''string'' happens: llOwnerSay(llGetOwner()); // works llOwnerSay("Your key is " + llGetOwner()); // FAILS - concatenation needs typecast llOwnerSay("Your key is " + (string)llGetOwner()); // works string OwnerKeyAsString = llGetOwner(); // works $lfn[llUnSit] accepts a parameter of type key. The following examples illustrate how automatic conversion from string to key happens: llUnSit("3d6181b0-6a4b-97ef-18d8-722652995cf1"); // works key Texture = TEXTURE_BLANK; // works (TEXTURE_BLANK is a string constant) How to initialize and how not to initialize lists with key values in the $globals declarations: key mykey = "3d6181b0-6a4b-97ef-18d8-722652995cf1"; // works list mylist = [mykey]; // works (this is how to put key-typed constants in globals) list mylist = [(key)"3d6181b0-6a4b-97ef-18d8-722652995cf1"]; // FAILS list mylist = ["3d6181b0-6a4b-97ef-18d8-722652995cf1"]; // works but it's a string, not a key list mylist = [NULL_KEY]; // works but it's a string, not a key Using $kw[if] to test validity of a key (complete example): default { state_entry() { // NULL_KEY prints "1 False": if ((key)NULL_KEY) llOwnerSay("1 True"); else llOwnerSay("1 False"); // "This is just text" is not a valid UUID, so this prints "2 False": if ((key)"This is just text") llOwnerSay("2 True"); else llOwnerSay("2 False"); // But keys are compared as strings, so this prints "3 True": if ((key)"This is just text" != NULL_KEY) llOwnerSay("3 True"); else llOwnerSay("3 False"); // A valid key meets the 'if' condition, so this prints "4 True": if ((key)"01234567-89ab-cdef-0123-456789abcdef") llOwnerSay("4 True"); else llOwnerSay("4 False"); // This should always print "5 True" because the prim's key is // supposed to be always valid: if (llGetKey()) llOwnerSay("5 True"); else llOwnerSay("5 False"); // Note that NULL_KEY is NOT a key constant, but a string constant. This // example will output "6 True" because it follows the string rules, not the // key rules. See the 'string' type or the 'if' keyword for an explanation. if (NULL_KEY) llOwnerSay("6 True"); else llOwnerSay("6 False"); } } // The output should be: // 1 False // 2 False // 3 True // 4 True // 5 True // 6 True // Note that llOwnerSay is subject to chat lag, so the order may differ in // rare occasions. That's why they are numbered. This function returns a valid UUID always and can be used to validate user input when it is supposed to be an UUID: key ValidateKey(string id) { if ((key)id) return llToLower(id); // convert to lowercase return NULL_KEY; }