LSL Protocol/RestrainedLifeAPI

From Second Life Wiki
Jump to navigation Jump to search

Restrained Life viewer v1.11 Specification

By Marine Kelley


Audience

This document is aimed at people who wish to modify or create their own LSL scripts to use the functionalities of the RestrainedLife viewer. It does not, however, explains LSL concepts such as messages and events, nor universal concepts such as UUIDs.

Introduction

The RestrainedLife viewer is meant to execute certain behaviours when receiving special messages from scripts in-world. These messages are mostly calls to the llOwnerSay() LSL function.

Architecture

The RestrainedLife viewer parses every llOwnerSay call and executes every command beginning with '@'. For instance, a call to llOwnerSay ("@detach=n") will tell the viewer that the object sending the message cannot be detached until further notice.

Version 1.10 and above are able to parse multiple commands in one message, in order to avoid spamming the user who is not using this viewer. The format of a message is therefore :

@<behaviour1>[:option1]=<param1>,<behaviour2>[:option2]=<param2>,...,<behaviourN>[:optionN]=<paramN>

Note that there is only one '@' sign, placed at the beginning of the message. The viewer understands this as "this whole llOwnerSay() is actually a command to execute", so no need to put a '@' before every command, it wouldn't even work. If at least one command fails (typo), the viewer says "... fails command : ... " and mentions it all. However correct commands are parsed and executed, only incorrect ones are discarded.

Warning : These behaviours are not persistent between sessions, and an object changes UUID everytime it rezzes. This means the object must resend its "status" (undetachable, preventing IMs...) in the on_rez () event as well as when it changes.

List of commands

Note : These commands are not case-sensitive but are spacing-sensitive. In other words, "@detach = n" will not work.

  • Automated version checking : "@version=<channel_number>"

Implemented in v1.0b Makes the viewer automatically say its version immediately on the chat channel number <channel_number> that the script can listen to. Always use a positive integer. Remember that regular viewers do not answer anything at all so remove the listener after a timeout.

Warning : when logging in, the on_rez event of all the attachments occurs way before the avatar can actually send chat messages (about half the way through the login progress bar). This means the timeout should be long enough, like 30 seconds to one minute in order to receive the automatic reply from the viewer.

  • Manual version checking : "@version"

Implemented in v1.0a This command must be sent in IM from an avatar to the user (will not work from objects). The viewer automatically answers its version to the sender in IM, but neither the message nor the answer appears in the user's IM window, so it's totally stealthy.

  • Render an object detachable/nondetachable : "@detach=<y/n>"

Implemented in v1.0a When called with the "n" option, the object sending this message (which must be an attachment) will be made nondetachable. It can be detached again when the "y" option is called.

  • Allow/prevent sending chat messages : "@sendchat=<y/n>"

Implemented in v1.0b When prevented, everything typed on channel 0 will be discarded. However, emotes and messages beginning with a slash ('/') will go through, truncated to strings of 30 and 15 characters long respectively (likely to change later). Messages with special signs like ()"-*=_^ are prohibited, and will be discarded. When a period ('.') is present, the rest of the message is discarded.

  • Remove/add an exception to the emote truncation above : "@emote=<rem/add>"

Implemented in v1.01 When adding this exception, the emotes are not truncated anymore (however, special signs will still discard the message).

  • Allow/prevent sending instant messages : "@sendim=<y/n>"

Implemented in v1.0b When prevented, everything typed in IM will be discarded and a bogus message will be sent to the receiver instead.

  • Remove/add exceptions to the instant message sending prevention : "@sendim:<UUID>=<rem/add>"

Implemented in v1.01 When adding an exception, the user can send IMs to the receiver whose UUID is specified in the command. This overrides the prevention for this avatar only (there is no limit to the number of exceptions), don't forget to remove it when it becomes obsolete.

  • Allow/prevent receiving chat messages : "@recvchat=<y/n>"

Implemented in v1.0b When prevented, everything heard in public chat will be discarded.

  • Remove/add exceptions to the chat message receiving prevention : "@recvchat:<UUID>=<rem/add>"

Implemented in v1.01 When adding an exception, the user can hear chat messages from the sender whose UUID is specified in the command. This overrides the prevention for this avatar only (there is no limit to the number of exceptions), don't forget to remove it when it becomes obsolete.

  • Allow/prevent receiving instant messages : "@recvim=<y/n>"

Implemented in v1.0b When prevented, every incoming IM will be discarded and the sender will be notified that the user cannot read them.

  • Remove/add exceptions to the chat message receiving prevention : "@recvim:<UUID>=<rem/add>"

Implemented in v1.01 When adding an exception, the user can read instant messages from the sender whose UUID is specified in the command. This overrides the prevention for this avatar only (there is no limit to the number of exceptions), don't forget to remove it when it becomes obsolete.

  • Allow/prevent teleporting to a landmark : "@tplm=<y/n>"

Implemented in v1.0 When prevented, the user cannot use a landmark, pick or any other preset location to teleport there.

  • Allow/prevent teleporting to a location : "@tploc=<y/n>"

Implemented in v1.0 When prevented, the user cannot use teleport to a coordinate by using the map and such.

  • Allow/prevent teleporting by a friend : "@tplure=<y/n>"

Implemented in v1.0 When prevented, the user automatically discards any teleport offer, and the avatar who initiated the offer is notified.

  • Remove/add exceptions to the friend teleport prevention : "@tplure:<UUID>=<rem/add>"

Implemented in v1.0 When adding an exception, the user can be teleported by the avatar whose UUID is specified in the command. This overrides the prevention for this avatar only (there is no limit to the number of exceptions), don't forget to remove it when it becomes obsolete.

  • Unlimit/limit sit-tp : "@sittp=<y/n>"

Implemented in v1.0 When limited, the avatar cannot sit on a prim unless it is closer than 1.5 m. This allows cages to be secure, preventing the avatar from warping its position through the walls (unless the prim is too close).

  • Clear all the rules tied to an object : "@clear"

Implemented in v1.0a, but working only since v1.04a This command clears all the restrictions and exceptions tied to a particular UUID.

  • Clear a subset of the rules tied to an object : "@clear=<string>"

Implemented in v1.0a, but working only since v1.04a This command clears all the restrictions and exceptions tied to a particular UUID which name contains <string>. A good example would be "@clear=tp" which clears all the teleport restrictions and exceptions tied to that object, whereas "@clear=tplure:" would only clear the exceptions to the "teleport-by-friend" restriction

  • Allow/prevent editing objects : "@edit=<y/n>"

Implemented in v1.03 When prevented from editing and deleting objects, the Build & Edit window will refuse to open.

  • Allow/prevent rezzing inventory : "@rez=<y/n>"

Implemented in v1.03 When prevented from rezzing stuff, creating objects, drag-dropping from inventory and dropping attachments will fail.

  • Allow/prevent wearing clothes : @addoutfit[:<part>]=<y/n>

Implemented in v1.10, added skin hair and eyes in v1.10.1 Where part is :

gloves|jacket|pants|shirt|shoes|skirt|socks|underpants|undershirt|skin|eyes|hair|shape

If part is not specified, prevents from wearing anything beyond what the avatar is already wearing.

  • Allow/prevent removing clothes : @remoutfit[:<part>]=<y/n> (underpants and underwear are kept for teens)

Implemented in v1.10, added skin hair and eyes in v1.10.1 Where part is :

gloves|jacket|pants|shirt|shoes|skirt|socks|underpants|undershirt|skin|eyes|hair|shape

If part is not specified, prevents from removing anything in what the avatar is wearing.

  • Force removing clothes : @remoutfit[:<part>]=force (*) (teens can't be forced to remove underpants and underwear)

Implemented in v1.10 Where part is :

gloves|jacket|pants|shirt|shoes|skirt|socks|underpants|undershirt|skin|eyes|hair|shape

If part is not specified, removes everything.

  • Force removing attachments : @detach[:attachpt]=force (*)

Implemented in v1.10 Where part is :

chest|skull|left shoulder|right shoulder|left hand|right hand|left foot|right foot|spine|
pelvis|mouth|chin|left ear|right ear|left eyeball|right eyeball|nose|r upper arm|r forearm|
l upper arm|l forearm|right hip|r upper leg|r lower leg|left hip|l upper leg|l lower leg|stomach|left pec|
right pec|center 2|top right|top|top left|center|bottom left|bottom|bottom right

If part is not specified, removes everything.

  • Get the list of worn clothes : @getoutfit[:part]=<channel_number>

Implemented in v1.10, added skin hair and eyes in v1.10.1 Makes the viewer automatically answer the current occupation of clothes layers as a list of 0s (empty) and 1s (occupied) immediately on the chat channel number <channel_number> that the script can listen to. Always use a positive integer. Remember that regular viewers do not answer anything at all so remove the listener after a timeout.

The list of 0s and 1s corresponds to :

gloves,jacket,pants,shirt,shoes,skirt,socks,underpants,undershirt,skin,eyes,hair,shape

in that order.

If a part is specified, answers a single 0 (empty) or 1 (occupied) corresponding to the part.

Ex 1 : @getoutfit=2222 => "0011000111" => avatar is wearing pants, shirt, underpants and undershirt, and of course a skin.
Ex 2 : @getoutfit:socks=2222 => "0" => the avatar is not wearing socks.
  • Get the list of worn attachments : @getattach[:attachpt]=<channel_number>

Implemented in v1.10 Makes the viewer automatically answer the current occupation of attachment points as a list of 0s (empty) and 1s (occupied) immediately on the chat channel number <channel_number> that the script can listen to. Always use a positive integer. Remember that regular viewers do not answer anything at all so remove the listener after a timeout.

The list of 0s and 1s corresponds to :

none,chest,skull,left shoulder,right shoulder,left hand,right hand,left foot,right foot,spine,
pelvis,mouth,chin,left ear,right ear,left eyeball,right eyeball,nose,r upper arm,r forearm,
l upper,arm,l forearm,right hip,r upper leg,r lower leg,left hip,l upper leg,l lower leg,stomach,left pec,
right pec,center 2,top right,top,top left,center,bottom left,bottom,bottom right

in that order.

If an attachment point is specified, answers a single 0 (empty) or 1 (occupied) corresponding to the point.

Ex 1 : @getattach=2222 => "011000011010000000000000100100000000101" => avatar is wearing attachments on 
chest, skull, left and right foot, pelvis, l and r lower leg, HUD bottom left and HUD bottom right.
Ex 2 : @getattach:chest=2222 => "1" => avatar is wearing something on the chest.

Note : The first character ("none") is always '0', so the index of each attach point in the string is exactly equal to the corresponding ATTACH_* macro in LSL. For instance, the index 9 in the string is ATTACH_BACK (which means "spine"). Remember the indices start at zero.

  • Allow/prevent using inventory : @showinv=<y/n>

Implemented in v1.10 Forces the inventory windows to close and stay closed.

  • Allow/prevent reading notecards : @viewnote=<y/n>

Implemented in v1.10 Prevents from opening notecards but does not close the ones already open.

  • Allow/prevent standing up : @unsit=<y/n>

Implemented in v1.10 Hides the Stand up button.

  • Force sit on an object : @sit:<UUID>=force (*)

Implemented in v1.10 Does not work if the user is prevented from sit-tping and further than 1.5 meters away, or when prevented from unsitting.

  • Force unsit : @unsit=force (*)

Implemented in v1.10 Self-explanatory but for some reason it randomly fails, so don't rely on it for now. Further testing is needed.

  • Allow/prevent using any chat channel but certain channels : @sendchannel[:<channel>]=<y/n>

Implemented in v1.10 Complimentary of @sendchat, this command prevents the user from sending messages on non-public channels. If channel is specified, it becomes an exception to the aforementioned restriction. It does not prevent the viewer automatic replies like @version=nnnn, @getstatus=nnnn etc.

  • Get the list of restrictions the avatar is currently submitted to : @getstatus[:<part_of_rule>]=<channel>

Implemented in v1.10 Makes the viewer automatically answer the list of rules the avatar is currently under, only for the object containing the script issuing that command, immediately on the chat channel number <channel_number> that the script can listen to. Always use a positive integer. Remember that regular viewers do not answer anything at all so remove the listener after a timeout. The answer is a list of rules, separated by slashes ('/').

This command is useful for people who write scripts that may conflict with other scripts in the same object (for instance : third-party plugins). Conflict do not occur in different objects, that's why this command only applies to the object calling it.

<part_of_rule> is the name of a rule, or a part of it, useful if the script only needs to know about a certain restriction.

Example : If the avatar is under tploc, tplure, tplm and sittp, here is what the script would get :
@getstatus=2222  =>  tploc/tplure/tplm/sittp
@getstatus:sittp=2222  =>  sittp
@getstatus:tpl=2222  =>  tploc/tplure/tplm  (because "tpl" is part of "tploc", "tplure" and "tplm" but not "sittp")
  • Get the list of shared folders in the avatar's inventory : @getinv=<channel_number>

Implemented in v1.11 Makes the viewer automatically answer the list of folders contained into the folder named "#RLV" (if it exists), immediately on the chat channel number <channel_number> that the script can listen to. Always use a positive integer. Remember that regular viewers do not answer anything at all so remove the listener after a timeout. The answer is a list of names, separated by commas (',').

  • Force attach items contained inside a shared folder : @attach:<folder_name>=force (*)

Implemented in v1.11 Forces the viewer to attach every object and wear every piece of clothing contained inside <folder_name> (which must be directly under "#RLV"). Objects names must contain the name of their target attachment point or they won't be attached.

Attachment point names are the same as the ones contained into the Attach To submenu : "skull", "chest", "l forearm"...

  • Force detach items contained inside a shared folder : @detach:<folder_name>=force (*)

Implemented in v1.11 Forces the viewer to detach every object and unwear every piece of clothing contained inside <folder_name>(which must be directly under "#RLV"). If "@detach" is used with an attachment point name (skull, pelvis... see above), it takes priority over this way of detaching since it is the same command.

  • Allow/prevent touching objects located further than 1.5 meters away from the avatar : @fartouch=<y/n>

Implemented in v1.11 When prevented, the avatar is unable to touch/grab objects from more than 1.5 m away, this command makes restraints more realistic since the avatar litterally has to press against the object in order to click on it.

  • Allow/prevent viewing the world map : @showworldmap=<y/n>

Implemented in v1.11 When prevented, the avatar is unable to view the world map, and it closes if it is open when the restriction becomes active.

  • Allow/prevent viewing the mini map : @showminimap=<y/n>

Implemented in v1.11 When prevented, the avatar is unable to view the mini map, and it closes if it is open when the restriction becomes active.

(*) Silently discarded if the user is prevented from doing so by the corresponding restriction. This is on purpose.

   Ex : Force detach won't work if the object is undetachable. Force undress won't work if the user is prevented from undressing.

Important note about the global behaviours such as sendchat

Such behaviours are global, which means they don't depend on a particular object. However, they are triggered by objects with a set UUID which can change, and several objects can add the same behaviour, which will be stored several times as the UUIDs are different.

This has a nice side effect : when wearing 2 locked devices that prevent chat, it is necessary to unlock them both to be able to chat again. But it has a nasty side effect, too : if the item changes UUID (for instance it was derezzed and rezzed again), and it doesn't allow chat beforehand, then the user will have to wait a short moment because the rule stays "orphaned" (its UUID is defunct) until the garbage collector kicks in.

Therefore : ALWAYS DEACTIVATE A BEHAVIOUR WHEN THE OBJECT THAT HAS ACTIVATED IT DEREZZES FOR ANY REASON BESIDES LOGGING OUT ! "@CLEAR" IS YOUR FRIEND !

Shared Folders

Since v1.11, the viewer can "share" some of your items with scripts in world in order to let them force you to attach, detach and list what you have shared.

To do this :

  • Create a folder named "#RLV" (without the quotes) directly under "My Inventory" (right-click on "My Inventory", select "New Folder"). We'll call this folder the "shared root".
  • Move a folder containing restraints or other attachments directly into this new folder, that's it !

So it would look like this :

My Inventory
|- #RLV
|  |- cuffs
|  |  |- left cuff (l forearm)
|  |  \- right cuff (r forearm)
|  \- gag
|     \- gag (mouth)
|- Animations
|- Body Parts
.
.
.

For example : If you're owning a set of RR Straps and want to share them, just move the folder Straps BOXED under the shared root.

- Either wear all the items of the folders you have just moved (one folder at a time !) or rename your items yourself, so that each item name contains the name of the target attachment point. For example : "left cuff (l forearm)", "right ankle cuff (r lower leg)".

The attachment point name is the same as the one you find in the "Attach To" menu of your inventory, and is case insensitive (for example : "chest", "skull", "stomach", "left ear", "r upper arm"...). If you wear the item without renaming it first it will be renamed automatically, but only if it is in a shared folder and does not contain any attachment point name already. If you want to wear it on another attachment point, you'll need to rename it by hand.

Pieces of clothing are treated exactly the same way (in fact they can even be put in the folder of a set of restraints and be worn with the same command). Shoes, for instance, are a good example of mixed outfits : some attachments and the Shoes layer. Clothes are NOT renamed automatically when worn.

GOTCHAS :

  • Do NOT put several levels of folders inside the shared root, it wouldn't work. For instance, do not create a folder named "Restraints" and put the "Straps BOXED" folder inside it.
  • Do NOT put a comma (',') in the name of the folders under the shared root or it would screw the list up.
  • Don't forget to rename the items in the shared folders (or to wear these items at least once to have them be renamed automatically) or the force attach command will appear to do nothing at all.
  • Avoid cluttering the shared root with many folders, since some scripts may rely on the list they got with the @getinv command and chat messages are limited to 1023 characters. Choose wisely, and use short names.


For your information

Here is how it works internally, for a better understanding of the gotchas you may encounter :

  • Each command is parsed into a Behaviour (ex: "remoutfit"), an Option (ex: "shirt") and a Param (ex: "force") and comes from an UUID (the unique identifier of the emitting object).
  • There are two types of commands : one-shot commands (those which Param is "force" and those which Param is a number such as the channel number of a "version" call) and rules (those which Param is "y", "n", "add" or "rem"). "clear" is special but can be seen as a one-shot command.
  • Parameters "n" and "add" are exactly equal and are treated exactly the same way, they are just synonyms. Same goes for "y" and "rem". The only purpose is to distinguish rules ("sendchannel=n") from exceptions ("sendchannel:8=add") in a script for clarity.
  • Rules are stored inside a table linking the UUID of the emitter to the rule itself. They are added when receiving a "n"/"add" Param, and removed when receiving a "y"/"rem" Param.

If UUID1 is a collar and UUID2 is a gag :

UUID1 => detach, tploc, tplm, tplure, sittp

UUID2 => detach, sendim, sendim:(keyholder)

Those two rules mean that the user cannot send IMs except to their keyholder, and cannot TP at all. Those two items are not detachable. Now if the collar sends "@sendim=n", the table becomes :

UUID1 => detach, tploc, tplm, tplure, sittp, sendim

UUID2 => detach, sendim, sendim:(keyholder)

If it sends "@sendim=n" a second time nothing changes, as there is a check for its existence prior to adding it. If the gag is unlocked and detached, either it sends a "@clear" or the garbage collector kicks in so the rules linked to UUID2 disappear. However, the avatar is still unable to send IMs even to their keyholder, as the exception has disappeared as well. This is because rules linked to one object don't conflict with rules linked to another one.

  • One-shot commands, on the other hand, are executed on-the-fly and are not stored.
  • When logging on, the avatar stays non-operational (cannot chat, cannot move) for some time, while the user sees the progress bar. However, worn scripted objects rez in the meantime and start sending rules and commands before the viewer can execute them. Therefore it stores them in a buffer and executes them only when the user is given controls (when the progress bar disappears).
  • The viewer periodically (every N seconds) checks all its rules and removes the ones linked to an UUID that does not exist around anymore ("garbage collector"). This means that rules issued by an unworn owned object will be discarded as soon as the avatar teleports elsewhere.