The avatar-controller is a program that can be used to control a Second Life or OpenSim avatar as a robot ("bot"). The program understands commands that can make the avatar stand, sit, look at a particular object, change an object's texture, and so on. Commands can be typed by the user on the console or can be taken from a file named in a script command.
The commands are described in later sections, below, and they include ones that are useful in scripts, and commands that find the names of things in the simulated world, as well as commands that tell the avatar what to do.
The avatar-controller works with two queues of input.
One contains the lines from any scripts that are being processed. Normally, it is either empty or else contains the remaining lines from a single script; however, if a script command is used inside a script, the lines from the script named in that command will appear before the remaining lines from the original script (and so on recursively).
The other queue contains everything else, where currently "everything else" means commands that the user types on the console plus any textual chat that the avatar hears. Each line of chat is turned into a chat-from command, so that all of the input that the program processes can be treated as commands.
Commands from scripts have priority. If the user types a script command, the program will run commands from the script, one by one, until they have all been handled. Any commands typed by the user during that time will not be processed until the script has finished.
The one exception to this is when the script is waiting for an event to occur, in which case input from the user (and from chat) will be examined, although it will not be executed as commands. For more on that, see the description of the wait-for command.
The program can play a sequence of sound files while it is processing other commands, or it can play a sound file and wait for it to finish. See the play-sound-sequence and play-sound-file commands.
Since we want to be able to refer to objects, textures, etc. by their names, rather than have to use their long and essentially meaningless "universally unique IDs" (UUIDs), it is often necessary to do something in order to find out their names; and then it can be useful to see a list of the known names, from time to time, in order to check what names can be used.
Therefore, there are "find-" and "list-" commands for most of the types of things we'll want to use. These commands are typically typed on the console when experimenting, or when "setting up" for an experiment.
For most types of things that can be referred to in commands (prims, avatars, textures, etc), their names are allowed to contain spaces. The one exception, at present, is sound files.
Each time the program is run, it creates a log file in the "logs" directory. The log files have extension ".txt" and have names that begin with "log" and then have numeric values for year, month, day, hour, minute, and second, separated by "-"s, that show when the program started running. Note that these names will sort so that later logs appear later in an alphabetically ordered list.
A log file contains a time-stamped line for each command that was processed, including comments.
The program expects to find certain directories ("sounds", "logs", "scripts") in certain places relative to its ".exe" file. Here is the expected structure:
TestProject TestProject bin Debug Release ... TestBot.exe ... logs ... log files ... scripts ... script files ... sounds ... sound files ...
Commands are described like this:
A description of what the command does.
Log in the indicated user / avatar. This is the avatar that will be controlled by the program.
Logging in currently happens automatically when the program is run instead.
Log out the avatar and exit the program.
Find the names of objects (prims) within the indicated distance from the avatar. The distance is believed to be metres and can be given as a decimal.
List the known object names.
Tell the avatar to look at the object. This effect persists until a stop-looking command is given.
Cancel a look-at effect.
Tell the avatar to turn towards the object.
Tell the avatar to sit on the object.
Tell the avatar to stand up.
Find the textures in the avatar's inventory "Textures" folder.
Find the textures in the object's contents.
List the known texture names.
Change the object's texture.
Find the sounds in the avatar's inventory "Sounds" folder.
Find the sounds in the object's contents.
List the names of known in-world sounds.
Play an in-world sound in-world.
Preload sound (.wav) files from the directory.
Preloading simply means that the data is read from the file now, so that it doesn't have to be read right before the sound is played. Preloading therefore allows sounds to start playing more quickly when a sound-playing command is given.
Sound files in the "sounds" directory are preloaded automatically when the program starts running.
List the names of preloaded sound files.
Play a preloaded sound file and wait until it's finished playing.
Play a sequence of preloaded sound files while continuing to process later commands.
There are not at present any working movement commands apart from the ones listed in the "Objects" section.
Change the outfit the avatar is wearing. This can also change the avatar's gender.
This command does not yet work reliably.
Has the avatar say the text in-world on chanel 0.
Reports chat that is heard by the avatar.
List the known sript names. They will be the names of any ".txt" files in the "scripts" directory. New scripts created while the program is running will be noticed.
Tell the program to take commands from a script file.
If a script command appears in a script, commands from the script it names will be processed before any remaining commands from the current script.
A comment. The "//" must be followed by a space.
Comments are written to the console and also appear in the log file.
Tell the program to stop taking commands for some number of seconds. The number can have a decimal fraction, so that "sleep 1.5" would sleep for one and a half seconds.
Note that sound sequences will continue to play during a sleep. Therefore, mixing sleeps with other commands lets you control what the avatar is doing while the sounds play.
Wait for a command that matches the pattern. A wait-for:
The pattern is treated as a regular expression (of the sort understood by the C# Regex class). This is explained further in the "cookbook" section below.
The matching command will typically be one produced by in-world chat -- see chat-from above -- but it doesn't have to be. It also doesn't have to be a valid command. For example, it would be possible to wait for "hoo"; and if a "hoo" command appeared, perhaps typed by a passing owl, it would end the wait even though the program would find it meaningless in any other context.
If the wait-for is in a script, the "wait" holds back later commands from the script but will still examine ones from the console. That makes it possible to end the wait by typing a command on the console, if desired.
Typing a wait-for as a console command, rather that using it in a script, is a convenient way to test what the pattern will match, by typing further commands to see what happens. For example, where the user types the text after "--"s:
-- wait-for .* weather Waiting for .* weather -- sunny day Skipping sunny day -- cloudyweather Skipping cloudyweather -- cloudy weather Found a match for .* weather: cloudy weather
Break out of a wait-for without having to match the pattern.
Warning: A wait-for will examine any commands that were input while the script was running and that have not yet been processed, and this includes any chat-from commands produced by chat, even though that chat occurred before the wait began. In some cases, this is ok; in others it wouldn't be.
Regular expressions are a convenient and much-used way to describe patterns in text, but they can be cryptic to the uninitiated. (Complex ones can be cryptic to almost anyone.) So this section explains some of the regular expressions that will most commonly be used in wait-for commands.
The main things to note about regular expressions are:
. matches any character * lets something match zero or more times + lets something match one or more times
So "a*b+" will match any number of "a"s followed by one or more "b"s. The combination ".*" is a way to say it doesn't matter what characters appear there. So "a.*b" matches anything that starts with "a" and ends with "b". Note that the regular expression "Touched." will match "Touched.", but it will also match "Touched!", "Touched3", and so on, which may be ok. To match exactly "Touched.", use "Touched\.".
Remember that chat comes through as a chat-from command, So you have to match the "chat-from" as well as the more interesting parts. Also, the object name and the chat text are separated by ": ".
wait-for chat-from .*: Touched
wait-for chat-from object-name: .*
with "object-name" replaced by the object's name.
wait-for chat-from object-name: Touched
with "object-name" replaced by the object's name.
wait-for chat-from answer.*: .*Touched.*