How to create a basic libopenmv bot for osgrid?

From libopenmetaverse - libomv - Developer Wiki

Jump to: navigation, search

Contents

Much Thanks

To the author of the basic libopenmv bot tutorial, who's form and function I hijacked, and reworked unto my own ends :)

Prerequisites

The following prerequisites are required in order for you to create your first bot by following this tutorial.

Real World

  • This tutorial assumes that you are proficient with building complex communications projects such as opensimulator or libopenmv. If this is not the case, please see the c# tutorials referenced below.
  • If you have no experience with the C# (c-sharp) programming language, you may be in a bit deep here - I highly recommend that you stop now and please follow the list of links to csharp tutorials located here.
  • A copy of the libopenmv libraries; you can get this by exporting the trunk from SVN and building it yourself or downloading the binaries from the latest release build [1]
  • The following tutorial uses nant and mono from the command line. it is very likely you will not need to download anything if you are using linux, but if you are using windows, get this IDE for free at Microsoft's website. If you are on windows, don't sweat it, you should be able to follow the original bot tutorial at How to create a basic libopenmv bot?, simply using the source code found here in place of that which is present there. If, in fact, you are on windows, you may also skip past the tutorial bits concerning the default.build file; it is not used by MS VS.

OSGrid

  • Any active account for use as a bot on OSGrid. You can register a new account at http://osgrid.org/. There are no registration or other fees to be concerned with at OSGrid.
  • The grid has to be up and logins must be enabled for residents when you run your bots.

Getting Started

Getting started is rather different from Visual Studio/Microsoft Windows when using nant/mono under linux. I wont get all crazy going into build dependencies and prerequisites here, as that material is covered elsewhere in this wiki - see the libopenmetaverse page Getting Started for more details.

I know just as much about nant as I could hack out of OpenSim's [2] build files after running prebuild.sh. Consequently, I use a very simple nant build specification, which is put together as a simple xml document. This is a Good Thing (tm) because that is exactly what nant wants.

The name of the nant build file is 'default.build', and it sits in a project directory alongside the bot code. It's contents are as follows:

 
<?xml version="1.0"?>
<project name="MyPetBot" default="build">
    <echo message="Project Directory is ${project::get-base-directory()}" />
    <property name="basename" value="MyPetBot"/>
    <property name="baseddir" value="/home/HiroP/MyPetBot"/>
    <property name="libsdir" value="/home/HiroP/opensim/bin"/>
 
    <target name="build">
        <csc target="exe" output="${basename}.exe" warnaserror="False">
            <sources>
                <include name="${basename}.cs"/>
            </sources>
            <references>
                <include name="System.dll" />
                <include name="System.Data.dll" />
                <include name="${libsdir}/OpenMetaverse*.dll" />
            </references>
        </csc>
    </target>
</project>
 
 

Expository Deconstruction

The default.build file illustrated above contains certain key tags that describe the build context. While not presented as richly in e.g., emacs or vim as is presented by the Microsoft VS GUI, it is somewhat simpler to get one's hands on, as all the relevant elements and properties appropriate to the cause are immediately at hand in the file.

It is fairly self-explanatory, but some definite points of interest are, for instance, the project tag - it sets the name for the project, and the default operation when nant is run. We will typically want this to be 'build', as shown in the example. Also of particular note are the property attributes for the project tag - observe how the 'basename', 'basedir', and 'libsdir' attributes establish where in the project the various dependencies and references are to be found. Finally, we see where the build target, output filename, source code location, and references are established in the csc tag.

I won't go into further detail about this, as I am painfully aware that this build file could stand some improvement, and equally painfully aware that I know little about the workings of nant. That being said, it is a testament to nant's utility that in my almost complete ignorance I was able to rapidly ascertain and adapt the nature and contents of this file as it (they) are produced by runprebuild.sh in the early stages of the OpenSim build process.


The Code

 
using System;                                                 
using System.IO;                                              
using System.Collections.Generic;                             
using System.Text;                                            
using OpenMetaverse;          
                                
namespace MyPetBot                                            
{                                                             
    class MyPetBot                                            
    {                                                         
        public static GridClient client = new GridClient();   
        private static string first_name = "My";           
        private static string last_name = "Bot";           
        private static string password = "*";           
 
        public static void Main()
        {
            client.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);
            string startLocation = NetworkManager.StartLocation("Burroughs", 128, 128, 28);
            client.Settings.LOGIN_SERVER = "http://osgrid.org:8002/";
            client.Network.Login(first_name, last_name,password,"My Bot Client", startLocation, "Hey it's me");
 
            Console.WriteLine("Bot Login Message: " + client.Network.LoginMessage);
        }
 
        static void Network_OnConnected(object sender)
        {
            Console.WriteLine("The bot is connected");
        }
     }
}
 

Expository Deconstruction

The references

 
using System;                                                 
using System.IO;                                              
using System.Collections.Generic;                             
using System.Text;                                            
using OpenMetaverse;
 

These references pull in all the dependencies for the bot's functionality from the referenced Class definitions. All of these but one (those that begin with 'System'), are typical of more common c# programs; the one of chief significance to our needs is the other, 'OpenMetaverse'. It, of course, provides the Linden Labs (tm) compatible Metaverse/VR network protocol (and other related) support for the bot application.

The GridClient Class

The GridClient Class is probably the most important Class in any OpenMetaverse application. It contains all of the functions that are required for your bot to communicate with the OSGrid or any other Second Life (tm) compatible grid. Usually this variable is named "Client," but you can call it whatever you want.

Defining some variables

After instantiation of the GridClient Class, we establish a few variables as a convenience when encoding the account credentials in preparation for login:

 
private static string first_name = "First";
private static string last_name = "Last";
private static string password = "password";
 

There is really no reason why the application name and version info shouldnt also be prepared in this way; I will leave that as an academic exercise for the user until such time as I get around to addressing it here.

The 'Main' Method

This is the entry point for any C# executable. If you don't know what this means, please pursue the tutorials here before continuing. In this implementation of the 'Main' Method, we perform most of the 'work' of the application (in case you hadn't noticed, our little bot here doesn't do much but teach). For our purposes, 'work' means setting up and making the call to Client.Network.Login. In addition, we set up a handler for the 'Network_OnConnected' event.

  • libopenmv applications are concurrent applications which execute over several threads; this libopenmv program actually doesn't terminate until you log your bot off of the grid.

The OnConnected Event

Client.Network.OnConnected += new NetworkManager.ConnectedCallback(Network_OnConnected);

The OnConnected Event (found under the Network class in your GridClient variable) is that event which is fired by the region once a successful login has been made. C# can be said, among other things, to be a richly event-driven language. Consequently, event handling is robustly implemented and widely employed as a fundamental coding mechanism. Here we see a canonical example of an event handler added to the list of such handlers that respond to the firing of our event, in this case the Network_OnConnected event implemented in libopenmv.

Logging In

if (Client.Network.Login(first_name, last_name, password, "My First Bot", "Your name"))

All is in readiness to make a call to Client.Network.Login(). This call actually brings it all together and logs the bot into the grid. This is also where literals are in place for application name and real name, though I have more frequently seen the 'real name' parameter called the 'version info string'. When this call is made, the various underlying network connections are made between authentication server, region server, and client - the credentials are provided, appropriately massaged and tested for validity, and if all is in order, the logical grid connection is completed and the bot logged in.

AN IMPORTANT NOTE:

This 'bot' code is actually Just Another Simple Client. Yep, that's right, there is no magic to a Bot. It's a client that is autonomous if for no other reason than it has no real user interface in any robust sense. Not to say it couldn't have, or that that interface might do something other than provide an interactive, immersive experience for the user; but for now, realize that for our purposes, there is fundamentally no difference between a tediously simple bot and a tediously simple grid client.


What if Client.Network.Login returns an error condition?

The Client.Network.Login() method returns a boolean; true is indicative of success and false indicates an error condition.

Console.WriteLine("I couldn't log in, here is why: " + Client.Network.LoginMessage);

A useful property found in the Network class is "LoginMessage." On an error, this string is filled with the error details. If there were no errors at login, the LoginMessage will contain the Message of the Day.

Logging out

Our bot doesnt log out - that is left for other, more complex tutorials to cover. For now, information on logging out (and problems related to logging out) can be found here: Logging Out

Running your bot

Now that you spent all that time writing your first bot code, it is time to compile and run the code for the first time.

On a linux system, this is very straightforward:

- Log into the box and open a command shell - cd into the project directory containing the default.build and your .cs file containing the c# source code for your bot - execute the command 'nant' - if all is right and proper in your default.build file, this will result in the creation of your executable - assuming a name of 'MyPetBot.exe' as the build target of your build processs, launch the bot by executing the command 'mono MyPetBot.exe' - this will start mono, and pass it the C# assembly containing our bot functionality.

Reprise

This code is tediously simple. The only operation the bot fulfills, beyond logging in and hooking up to the 'successful connection' event, is to notify us that it has, in fact, logged in successfully.

Obviously much more could be done with this, and I hope that you take it much farther than the jumping-off point I have provided here.

While there isn't a lot that can go wrong with this code, provided it is accurately transcribed, successfully built, and connected to an operational grid, the world is not perfect; and oftentimes some part of a recipe is omitted, rewritten, or extended, in directions that do not always yield immediate success, whether by incident, intent, or accident; in those cases, it is often productive to share and compare (or as my good friend cfk at osgrid likes to say, 'Cuss and Discuss') problems and solutions with others. To that end, send an email to the mailing list or see if any of the many fine people working on libopenmv are around on IRC to get some more help.

I hope you have found this tut usefull and informative - questions, comments and critiques are desireable and solicited. Please email me at james dot stallings at gmail dot com as needed.

Cheers!