You are currently not logged in! Enter your authentication credentials below to log in. You need to have cookies enabled to log in.
The key type is similar to the 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:
For example, 5748decc-f629-461c-9a36-a35a221fe21f is the UUID for TEXTURE_BLANK. The hexadecimal characters are output in lower case by all functions that output them (such as llGenerateKey
), and are accepted in either case by all functions that accept them (such as 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, 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 NULL_KEY.
Note that since the key type can hold any string, it can be (and has been) (ab)used to fulfil the same role as a string (for example, in link_message events).
Type conversion between string and 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 constants that hold UUIDs are not of type key
, but string
. This is mostly relevant when storing keys in a list, because the elements need the correct type when used with functions such as llListFindList
or 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.
By using if (value)...
, where the type of value
is 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 if
statement and others that accept conditions (while
, do-while
, for
). In contrast, the expression value != NULL_KEY
will also be 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 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.
llGetOwner
returns a key, and 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
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 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; }