Introduction
This document describes how data is passed between the following elements of the RezMela system:
RezMela control board script
RezMela (generic) world object script
RezMela (generic) icon script
RezMela scene notecard
Client world object script (eg Ground Map controller)
Client icon script (eg Ground Map icon)
This covers the establishment of two-way communications between the client world object and icon object scripts, and between them and the system scripts, including the storage of "extra data" - that is, free-format text data that applications can store in the scene notecard, and which may be loaded along with the scene. Extra data allows, for example, the ground map to store its coordinates, so that when a scene using a world map is loaded from notecard, the correct coordinates are used.
These features were initially developed for the Label Board and Ground Map applications, but are designed to be available to any client applications that need these features.
Use of messages
Linked messages (llMessageLinked()) are used to communicate between scripts in the same object. As is standard practice throughout our systems, the integer portion of the linked message is used to contain a unique code which specifies the type of message, and data is contained in the string portion and sometimes the key portion.
Link message codes are referenced internally by pseudo-constants with upper-case names.
For separate objects, where possible the osMessageObject() command is used. In this case, the command and data are both contained in the string (there are no other data parts), and are typically separated by | (pipe) symbols.
The commands llDumpList2String() and llParseStringKeepNulls() are often used to pack and unpack data that is contained in strings.
Interactions
1. Informing the client world object about its extra data and associated icon
When a world object is created, whether it's a new one or one loaded from a saved scene, the RezMela World Object script periodically sends to the client script the link message RWO_INITIALISE (808399110), which contains the Extra Data in the string and the UUID of the icon object in the key portion. These messages may be turned off by sending -RWO_INITIALISE (-808399110).
Using that UUID, it is possible for the client world object to send data to its associated icon. However, note that since the generic world object and icon scripts are agnostic about their respective clients (and indeed, there may in theory be several), this UUID will be that of the root prim of the icon. If the client icon script is in a non-root prim, it will not receive osMessageObject() messages sent to that UUID.
However, it is also possible to send messages to the client icon script via the generic icon script. To do this, the world object may send the generic message IC_COMMAND (1020) plus any specific data. This data will then be passed to the client icon script in a linked message with the numeric value of IC_COMMAND.
This function in the generic world object script may be used to send a string of text to the generic icon script:
MessageIcon(string Text) {
if (IconUuid != NULL_KEY && llKey2Name(IconUuid) != "") {
osMessageObject(IconUuid, (string)IC_COMMAND + "|" + Text);
}
}
and the text may be received in the generic icon script as follows:
link_message(integer Sender, integer Number, string Message, key Id) {
if (Number == IC_COMMAND) {
WorldObjectUuid = Id;
string Text = Message;
}
}
This may be picked up by the icon as described in section (3).
Note that the generic world object script is also receiving the Extra Data, or a null string if there is none. The messages are sent repeatedly to ensure that they are received when the destination script is loaded and ready to receive them - a crude but simple way of coordinating the readiness of both scripts, and more reliable and faster than (say) a llSleep() call.
2. Storing extra data
The world object client can store extra data at any time by issuing the following command:
integer RWO_EXTRA_DATA_SET = 808399102;
string ExtraData;
[... ExtraData is set ...]
llMessageLinked(LINK_SET, RWO_EXTRA_DATA_SET, ExtraData, NULL_KEY);
The generic world object will then send this data to the control board script, and it will be stored as part of the scene notecard.
The Extra Data stored will be passed back to future instances of the script via the RWO_INITIALISE command described in section (1).
3. The client icon script receives data from the world object
When IC_COMMAND is used to send data to the icon script, it may be picked up like this:
link_message(integer Sender, integer Number, string Message, key Id) {
if (Number == IC_COMMAND) {
WorldObjectUuid = Id;
string Text = Message;
This is also how the icon script can learn the UUID of the associated world object. If may be useful to pass dummy data from the world object to the icon if the icon needs that UUID - for example, as described in section (4).
4. User communication with the world object via the icon
It is possible for interaction with the icon to be passed to its corresponding world object.
Typically this will be done using a "hamburger" menu icon prim linked to the icon object. This prim may contain a script which has a touch_start() event (thus preventing the generic icon script from interpreting this as a selection, etc), and which sends to the generic icon script a specific command value and the UUID of the user from llDetectedTouch().
To simplify matters, it's recommended that the icon merely serve as a trigger, and that the world object is the one that continues user interaction, eg by presenting menus, etc.
The entirety of the menu script for the ground map icon menu prim (which triggers a menu from the world object) is as follows;
integer IC_MENU = 1021;
default {
touch_start(integer Count) {
llMessageLinked(LINK_SET, IC_MENU, "", llDetectedKey(0));
}
}
and this is picked up by the ground map icon script like this:
link_message(integer Sender, integer Number, string Message, key Id) {
if (Number == IC_MENU) { // Someone has clicked on the menu icon
MessageController(llList2CSV([ "menu", (string)Id ]));
}
[...]
The function MessageController() passes text (in this case, the word "menu" and the ID of the user, comma-separated) to the client world object script:
integer WO_COMMAND = 3007;
[...]
MessageController(string Text) {
if (WorldObjectUuid != NULL_KEY && llKey2Name(WorldObjectUuid) != "") {
osMessageObject(WorldObjectUuid, (string)WO_COMMAND + "|" + Text);
}
}
Note that the function will do nothing if the world object is not known or if it doesn't exist in the region, in order to prevent script error messages being sent to the viewer.
The WO_COMMAND value will cause the generic world object script to echo that data in a linked message with the same command value. So, in that script, we have:
link_message(integer Sender, integer Number, string String, key Id) {
if (Number == WO_COMMAND) {
list L = llCSV2List(String);
string Command = llList2String(L, 0);
string Params = llList2String(L, 1);
if (Command == "menu") {
MenuAvId = (key)Params;
ShowMenu();
[...]
The osMessageObject() data is thus converted into a linked message, meaning that it doesn't matter if the receiving script is not in the root prim.
Note that the format of the text payload itself (menu + "," + UUID) is only a suggestion, based on the usage of this feature by the ground map.