LSL To Client Communication
Communication
A mechanism is needed to allow LSL scripts to talk to the viewer in order to allow implementing some interesting functionality, such as viewer UI extensions that communicate with in-world objects, for instance. Viewer to LSL communication is easily possible, by making the viewer talk on a specific channel, or use XML RPC. This may not be ideal for all cases, but it's already doable without any modifications.
What needs work is LSL to Client communication, as there currently isn't any good method in the official client for that.
Requirements
A robust mechanism should satisfy these requirements:
- Scripts must be able to receive messages from the viewer (can be done already with chat and XML RPC)
- Scripts must be able to reply to the viewer
- It must be possible to communicate with multiple viewers at once without confusion
- Order of delivery must be guaranteed (chat messages currently can be reordered)
- Messages must be reliable
The hack below can satisfy requirements #1 to #3. Requirement #4 would require extra work (although it's doable) and is possibly best ignored, as LL mentioned the possibility of moving chat to TCP, which would automatically solve the issue.
Requirement #5 is mostly satisfied as data isn't lost, and the only problem may be with the viewer or the script disappearing, which can be dealt with by designing the proper protocol, if needed.
Hack
While there's no official solution, here's what I came up with for now:
- Client to LSL: Client speaks on a channel directly. Nothing special here.
- LSL to Client: Script uses llOwnerSay, with this format:
$VwrComm$VERSION$COMPONENT$DATA
Fields:
- VwrComm: Header, must be present
- VERSION: Protocol version
- COMPONENT: Component inside the viewer the message is for
- DATA: Data being sent. The format of the data isn't specified.
Behavior
This is how the current implementation handles the protocol:
- Message must come from an object. Normal chat doesn't trigger it
- String gets split by "$" and must have at least 4 tokens
- First token must be VwrComm
- Second token must be "0" (version number, this will change)
- Third token matches the name of a known component.
If requirements #1 to #3 aren't satisfied, the string is passed as-is, and the code doesn't suppress its display.
If requirement #4 isn't satisfied, the text won't appear on screen, but the code won't continue further either. A message will be logged in the viewer's log, saying that a message with the wrong version was received.
If requirement #5 isn't satisfied, display is also suppressed, and a message is also logged.
If all those requirements are satisfied, the data in the message is sent to the specified part of the viewer for futher processing.
Example
$VwrComm$0$AvatarScanner$LoginComplete
Implementation
Code for this can be found at [1], line 2047
Note that at the time of writing, the client isn't capable of telling the difference between object speech sent to all users (llSay/etc) and object speech sent only to the owner (llOwnerSay). It also doesn't check the speaking object's key or its owner's. This code must be fixed to obtain that information, so that the viewer can ignore messages from objects not owned by the user, when such a thing is necessary.