The Wayback Machine - https://web.archive.org/web/20090426231903/http://www.adamfrisby.com:80/blog/

Adam Frisby

MRM: Language Contributions

without comments

If you are a coder and like the work I have been doing on MRM so far - I’m keen to accept any contributions you may have to the langage - patches on mantis are welcome (here’s how to submit). That being said, I am being somewhat restrictive with API-changing patches to ensure we have a consistent easy to understand language rather than a patchwork quilt of random features. The following is the list of rules I am using for language inclusions;

Coding Standards - The Rules for API Changes

The MRM API is designed to ‘feel’ like the official .NET API in as many ways as possible - this means it should be consistent and easy to understand. The same types and interfaces should be re-used in as many places as possible, duplication is to be strongly shunned.

1. Class Library Design and Naming

For core API (those items distributed with OpenSim), you must follow the Microsoft .NET Coding Standards for naming and class design.

2. Subclassing and Inheritance

Subclass (or subinterface) where possible to make a useful inheritence chain. The following is the current proposed structure for MRM entity inheritance.

Fig 1. IEntity Inheritance

Fig 1. IEntity Inheritance

Note that the above proposal is not set in stone - the alternative I am considering is inheriting IPlant from IObject, and making a new IPrimitiveObject - where we move prim related properties (such as Shape) into the subinterface.

3. “Superglobals”

You should insert items into the “Superglobals” appropriately. Superglobals are the [presently three] properties which are inherited from MRMBase. In the user-accessible language these are items such as “Host” or “World”.

3.1 Host Superglobal

Host means “Scripting Host”, items in Host should be directly related to the runtime environment the script is running in, such as performance characteristics, security permissions, etc. - it could almost be seen as analoguous to “System.Environment”.

Items placed into Host should be related to the runtime environment that is hosting the world itself. For instance, a database interface would be appropriate for ‘Host’ since it is unrelated to the world itself and is something that is dependent on the runtime environment.

3.2 World Superglobal

World refers to the SceneGraph - and should contain elements which are reflected inside the visual environment. For instance Avatars, Objects and other items which exist in the ‘World’. This also includes properties of the world itself, such as lighting conditions, sun angle, etc.

4. No Assumed Parameters

MRM API entries should not be designed with an assumed ‘target’ - that means that you should never ever assume you know the data the user will be processing unless it is directly connected to the object the user is calling the method on. Using an LSL function as an example, you should be able to quickly understand this rule.

BAD: llSetPos(vector3 pos); // Sets the position of the host object.
GOOD: llSetPos(IObject target, vector3 pos); // Sets the position of ‘target’

It should be noted that methods inside an object are free to act on themselves (eg IObject.Position is free to operate on the IObject instance), this only applies when referencing an outside object (such as say IAvatar.SitOn should have an IObject parameter and not assume which object to sit the avatar on).

5. Do not use OpenSim Types.

This means do not expose OpenSim internals to the MRM programmer - that means never return SceneObjectGroup, ScenePresence or any other internal representation to a MRM programmer. MRM provides replacements which take these as constructors in the form of IObject/IAvatar/etc’s implementors (SOPObject, SPAvatar, LOParcel, …)

If MRM does not implement your specific internal in an interface already, you must write an interface that can be passed to MRM programmers. The internal data should not implement the MRM “IAbcd” interface but instead a proxy should be written (see SOPObject for an example).

There is two reasons for this - the first is that passing internals means that any internal change will break MRM scripts. The second reason is security - security can be implemented inside the proxy whereas it cannot be implemented in the internal class.

6. Use OpenMetaverse.Types

libOpenmetaverse provides a number of useful types such as UUID, Vector3, etc. Use these whereever possible - for instance when representing U/V coordinates use “Vector2″.

7. Use the most appropriate Type for the job.

Do not use Vector3 to store only two values - use Vector2. There is a lot of types availible to use - make sure to pick the right one for the right job.

8. Do not copy LSL needlessly.

This is a big one - do not assume the LSL function set is an ideal to be upheld. Ask yourself when implementing a MRM replacement, “What is the using developer trying to do?”. Take the llSay, llShout, llWhisper, llRegionSay group - each implements the same underlying task, however the differing methods have a varying ‘range’ depending on which one is called.

For instance, llShout will ’say’ 100m. llSay will ’say’ 20m. A using developer is going to pick between them based on which range they need — but what if they need another range? Wouldnt it be smarter to have Object.Say(string message, int range)? Not only have you reduced the number of functions - but you have given the user more power.

9. Name Consistently

If you use a function name ‘SetFoobar’, the ‘GetFoobar’ should be called exactly that. Do not have ‘SetFoo/FooGet’, or ‘SetFoo/Foo’. (Note in practice, Set/Gets should always be implemented as C# properties.) To use LSL as another example - we should never end up with a pair like ‘llGetTextureOffset’ and ‘llOffsetTexture’.

10. Do not implement abitrary limits.

Copying from earlier, “If you have to, make them configurable. An example of this is the mandatory sleeps in LSL on functions like llEmail. Assume instead that people writing scripts in MRM know what they are doing.”

If you are implementing limits on particular MRM functions, make sure you have a damn good reason for it - you should assume MRM authors are region operators. If you implement specific limits, make sure you load them from OpenSim.ini.

“Safe” Areas to Contribute to

If the above has made you uncertain about contributing - there are a number of areas you can contribute safely towards, and they are pretty easy to find in the codebase.

  • Look for “throw new NotImplementedException()” inside the code base - in classes such as SOPObject you can safely implement these functions and properties and nearly guaruntee your patch will get accepted.
  • Suggestions - if you dont feel capable of writing a specific function, leave me a comment with something you want to see. Either myself or someone else may take it up and implement it.
  • Documentation - I’m using XMLDOC to build the final API documentation, so inserting ///<summary> and other XMLDOC tags into the codebase is always appreciated. Make sure to do the commenting on the interfaces themselves and not their implementations (eg files starting with “I”).
  • Tests and Examples - Post MRM scripts and write test scripts, these will eventually be rigged up to our internal testing framework, so the more functionality tests the better.
0 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 25th, 2009 at 5:48 am

Posted in OpenSim

Tagged with , ,

MRM: Microthreading Functions

without comments

When running an infinite loop or other computationally expensive function, you will often want to release processing time back to the region to avoid causing undue ‘lag’. For instance - in a sim with 4,000 colour changing scripts, each will be trying to pummel the CPU simultaneously to get their updates onccuring.

What ends up happening is each will run for a fairly long period of time until broken up by a processing expensive “thread switch” at which point the next gets a long run before going to the next and the next and the next, or alternatively - none will finish and only one will be running.

The following diagram explains this in action - script A runs until there is an expensive thread switch, at which point script B will commence operation. You can manually force a thread switch through the use of the “llSleep(0)” statement in LSL, however the cost of switching threads is still present.

Fig 1. Normal Threaded Scripting

Fig 1. Normal Threaded Scripting

Microthreading allows you to say “You can pause and give time to another script” - in a way that is very lightweight and easy for the runtime VM. You manually insert breakpoints into the script which define points between the ‘tasklets’, at these points the VM can switch between runtime contexts without any penalty. As a result you can have thousands of them without problem; when running time is divided between all the running threads evenly - broken up at the tasklet borders.

The following diagram shows the same as above, in a microthreading environment.

Fig 2. Microthreaded Runtime

Fig 2. Microthreaded Runtime

C# supports a limited form of microthreading via something called the “yield” keyword - and a lot of people have recognised you can use it to build a state machine — the basis of microthreading. Where we apply this to MRM is with some additional keywords.

The basic C# microthreading can be implemented in MRM without any additional work - however there is a significant manual cost in typing the construction of a microthreaded function. I have added two new keywords to MRM scripts today, which map to the C# yield statements.

The first is “microthreaded” - this keyword is inserted between the public/private/protected/internal keywords at the beggining of the function, and the variable type.For example, “private microthreaded void MyFunction(…) {”. Microthreaded functions can only work on functions with a no return type (void) - and internally it works by replacing “microthreaded void” with “IEnumerable”.

The second important keyword is “relax” - this keyword is defined as a breakpoint - an area where the VM can switch into another microthread without a penalty. There is a very small cost in placing these statements into your code, so consider placing them liberally. Place them inside of any loops or other routines which have a total processing time in excess of 2 milliseconds.

The relax keyword can only be placed inside of functions marked microthreaded - and you cannot call microthreaded functions directly (as in “Function(params)”). You must place microthreaded functions into the host scheduler marked as ‘Host.Microthreads.Run(myfunc(params));’

Another important note is that microthreaded functions will run asynchronously to your code, so do not expect “Microthreads.Run(…)” to block, consider it more a ‘Microthreads.ScheduleToRun(…)’. If you take these penalties into consideration however, these Microthreads can provide an excellent way to optimize your scripting and write coroutines relatively easily and quickly.

By default, the MRM VM will run 1,000 microthread tasklets per frame (or optimally 45,000 per second), this can be tweaked from inside of MRMModule.cs, however will eventually move into the OpenSim.ini [MRM] section.

The following is an example script that uses MRM microthreads.

Enjoy.

0 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 24th, 2009 at 6:14 am

Posted in OpenSim

Tagged with , , , , ,

O3D: Colour me impressed

with 6 comments

My first reactions to Google’s new O3D JavaScript API is “Thank God someone finally did it.”, a more detailed examination appears to yield something like Mozilla’s proposed Canvas3D but with practical implementations for all the major browsers and platforms (IE, FF, Win, Lin and Mac) - something Canvas3D was unlikely to get.

Fig 1. O3D Beach Sample

Fig 1. O3D Beach Sample

O3D has the advantage of being really the first proper 3D implementation for a browser to market (I won’t count Flash3D here since hardware accelleration is key to doing serious work with 3D.), it’s in ECMA/Javascript which makes it pretty accessible to a wide group of developers - and the API appears to be logical and powerful.

It’s backed by Google which will make overall deployment better - and I would be keen to wager that this endevour goes a lot further than Lively did. The runtime is even availible under the BSDL - which makes it very attractive to commercial users.

Could someone implement a virtual world with it?

I think for singleplayer games O3D is perfect - it’s easy to deploy, easy to write, uses standard file formats. Multiplayer - where VW’s come in is a much tougher nut to crack because there is still a dearth of reasonable communication standards for browsers.

AJAX is by communications standards not very powerful - it relies on the idea of a single thread carrying request/response packets. It can be hacked up into supporting threaded packeted communications - but I believe any virtual worlds using O3D will probably be those that can survive a larger latency (eg There.com(R) versus Second Life(R)) - worlds using it will use a lot more clientside processing to minimise connection loss.

The discussion on #opensim-dev this afternoon about O3D has been promising - it holds a lot of potential, and whether we can utilize it to write a simple browser plugin is going to be an interesting project for the next few days.

Graphically O3D has most of the niceties that a modern 3D engine expects (Shaders, etc) - the keys are going to be in the difficulty of writing scene and state management in Javascript, and making sure the communications systems are as simple and efficient as possible.

The ease of install and the lack of serious memory limits on the 3D scene means this may be a better option than Java3D for an accessible virtual world. Stay tuned.

1 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 22nd, 2009 at 8:37 am

Posted in Technical

Tagged with , , , , ,

MRM: Language Extensions and Libraries

with 2 comments

As of r9240, MRM now has proper support for language extensions - these come in two key flavours - the first is the ability to import outside .NET DLLs which allow you to load foreign libraries into your code, this could take the form of more advanced math libraries or other useful tools. Those libraries will be loaded with the same security context as your MRM - so when CAS is implemented in MRM for security, you will need to be aware that they will be affected too.

The syntax for importing a library is fairly simple - just place within your code, below the //MRM:C# line, a line which reads like this:

//@DEPENDS:MyLibrary.dll

Dependencies are requirements - if the dependent DLL cannot be found, it will throw a compile error, even if no code utilizes this extension.

Accessing Region Modules

The second form of language extension - the preferable one is to connect with other OpenSim region modules. Internally in OpenSim when a region module wishes to communicate with another module, it is done via a shared interface - one module will define an interface it can be accessed by (eg, IMRMModule)

Communicating with an MRM is done in a very similar fashion - you must create an interface that the script can utilize to connect to your module. This is best illustrated with an example, so printed below is a “Hello World” module, it’s structure is pretty simple.

The Module Code

A sample MRM using the above

This code represents a fairly simple example - there are a few considerations to make however when writing MRM interfaces, especially if you desire to get those interfaces into the core OpenSim distribution.

Good practices when writing a module interface

These are based loosely on the rules I am employing in designing the default API.

  • Use MRM types where possible - if you need to get an object as a parameter, utilize IObject rather than pass a UUID or localID. You can convert between them pretty easily (SOPObject takes LocalID as a singular constructor, and you can fetch it off via IObject.LocalID).
  • Do not pass in internal OpenSim classes. This means do not ever return something like SceneObjectPart - this is because OpenSim internal classes change, and when they change your MRM will break. If you need to use one of these classes and MRM doesnt have a matching interface already, make a new interface and contact me for possible inclusion in the standard distribution.
  • Do not require IHost for anything. If you want the user to pass in the host object, ask them to do it - but do not require it. This is because someone may find it useful to utilize your function on a remote object. By using IObject you make your module more useful to programmers.
  • If you need a unique ID for the script instance, require a UUID to passed, then request the user uses the global variable “ID”. This is a UUID that corresponds with the internal Inventory Item UUID of the MRM script.
  • Do not place abitrary limits on scripts. If you have to, make them configurable. An example of this is the mandatory sleeps in LSL on functions like llEmail. Assume instead that people writing scripts in MRM know what they are doing.
  • Follow MSDN C# Coding Guidelines. We use the MSDN Class Library coding standard in OpenSim, MRM by extension uses the same guidelines.

Happy Extending!

2 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 21st, 2009 at 5:51 am

Posted in OpenSim

Tagged with , ,

Someone at Adobe has a sense of humour

with one comment

As seen in Adobe Illustrator CS3

As seen in Adobe Illustrator CS3

0 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 20th, 2009 at 2:02 am

Posted in Uncategorized

Tagged with ,

Idealist/MXP

with 2 comments

It’s been a number of months since I last looked at the State of Open Viewers back in december.

Since then there has been some coalescence on Idealist as the platform-of-choice for the future viewer. While Xenki has some definete nice features (browser access, reasonable UI), it has some problems too (32-bit only, security sandbox issues, etc)*. I’m hoping we’ll be able to take some of the UI handling code (camera control, etc) from Xenki and import it into Idealist to get a best-of-both result.

Right now, the Idealist renderer is pretty good - it’s rendering things close to 90% accuracy, the remaining 10% include avatars (a somewhat complex topic), some sculpted parameters, and special effects (glow, bump maps, etc.). The following two screenshots should give you a good approximation of the rendering capabilities of Idealist right now.

Fig 1.1 - Idealist Viewer

Fig 1.1 - Idealist Viewer

By contrast, the same scene in the Second Life viewer is fairly similar

Fig 1.2 - Second Life Viewer (1.22)

Fig 1.2 - Second Life Viewer (1.22)

You can view this scene on OSGrid.org, it’s in the region “DTL Welcome Center” (a side project to build a new Orientation Island for osgrid.) - it makes a good test of a renderer since it uses almost every graphics feature on offer right now.

The most noticable differences between the viewers in terms of accuracy come down to a couple of minor but fixable points

  • Texture alignment - Idealist doesnt process extra texture parameters; rotation, scale, offset, etc. Most of these are fairly simple to implement, so this should not pose any long term difficulties.
  • Mirror X / Invert Sculpt Parameters - Idealist doesnt process these flags, so some of the sculpts are inverted (noticably the orange signs).
  • Alpha smoothing - Idealist produces ‘rough edges’ on alpha surfaces, this is fixable with some tweaking of the renderer parameters.
  • Texture Downloads - Not a bug in the renderer, however the texture download routine suffers issues with download speed and incomplete downloads. This is somewhat fixed in MXP due to MXP using plain HTTP for asset distribution - but under LLUDP some additional work needs to go into libomv to handle asset transmission better.

While that is not an exhaustive list - the current feature state is pretty good. Where work needs to go right now is in user interface (doing cross platform UI with 3D surfaces under .NET is interesting, let me assure you.) - one of the UI proposals I have been working on is pictured below.

Designing a Viewer UI

Fig 2.1 - Idealist UI Mockup

Fig 2.1 - Idealist UI Mockup

The main idea being to reduce clutter where possible - things such as Inventory are needed often, but arent needed permanently. Implementing these as a docking toolbox allows you to expand the inventory dock quickly and easily - while not having it consume significant screen real estate unnessecarily. As mentioned above - getting a design like this to work cross platform is difficult, infact it may even be easier to write a UI toolkit for Irrlicht than to attempt to embed Irrlicht into a UI toolkit while maintaining cross platform support.

MXP

One of the more interesting features of Idealist is the ability to connect a client on the newly implemented MXP handler. While getting it running requires a lot of technical knowledge right now - the MXP protocol has a lot more potential than the LLUDP one does for expansion and interactivity. There are also a number of improvements MXP makes to the transport layer which should improve scalability for the server.

Fig 3.1 - Idealist/OpenSim via MXP

Fig 3.1 - Idealist/OpenSim via MXP (source)

You can play with the MXP version by using the MXP branch of IdealistViewer, use the following settings when doing an SVN checkout

SVN URL: http://forge.opensimulator.org/svn/idealistviewer/branches/idealistviewer_mxp_0_0_1
SVN Username: anonymous
SVN Password: anonymous

There are some other benefits visible on LLUDP too, including a fixed water shader, better terrain handling and other renderer improvements which have not yet been migrated back to Idealist Trunk. When connecting, you will need to connect to the region in the format “mxp://ip:1253/<region uuid>/Test/” - note that on public grids exposing your region UUID can be a risk (some work being done on improving this).

Contributing

Finally, there’s a call for some contributors to Idealist - right now the major developers are also major OpenSim developers. We’re looking for some graphics specialists to come in and help with the design of Idealist - there’s a number of bugs and features which could do with patches, so if you are interested, please hop in #idealist-dev on Freenode.

I’ll repeat the call for Xenki if anyone is interested, I’m currently looking for a new maintainer to take over the role. Shoot me an email (see contact page for details) if you are interested in taking over the lead developer role on the project. (Update: Maintainer has been found.)

1 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 19th, 2009 at 12:52 am

Posted in Idealist, OpenSim, Xenki

Tagged with , , ,

OpenSimulator Graphics

with 2 comments

I’ve noticed in lots of places people have been using the OpenSimulator graphic on our website, background image and all.

What you may not have noticed is that there’s actually a copy of the original SVG on the wiki. (Licensed CC-By-SA with exceptions.). The image is a tri-tone graphic that is suitable for print work (we used it for the VW Expo in LA), the original graphic was done by myself, then adapted by Gryc and finally re-adapted by myself.

For those of you who want something you can just download, crop and resize, here’s some raster copies of the image.

opensim_blackopensim_white

License information as follows:

Licensed CC-BY

Please read down for exemptions.

License Code:

OpenSimulator Logo by Adam Frisby and Gryc is licensed under a Creative Commons Attribution 2.5 Australia License. Permissions beyond the scope of this license may be available at http://opensimulator.org/wiki/Image:opensimulator.svg.

Exemption #1

This logo may be used and modified at whim for any products, services, companies, promotion or similar of any product substantially derived from the original Open Simulator software, or is related to it (such as plugins, modules, content, compatible software, etc), as long as the resulting image is intended to convey association with the original Open Simulator software.

If this is not the case, you may still use the original Creative Commons Attribution license linked above to redistribute or modify this image.

Exemption #2

The logo design may be used, distributed or embedded in an unmodified form without attribution as long as the logo text (”OpenSimulator”) remains on the image.

2 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 13th, 2009 at 8:28 pm

Posted in OpenSim

Tagged with ,

Persistent Vegetative Simulation

with 3 comments

If a tree falls in a forest and nobody can see it, does it still fire a collision event?

In Second Life(R) it does, and this is one of the reasons that the platform is so expensive - maintaining 20,000 regions requires 20,000 processor cores. Consider the WWW by contrast - a single server can power thousands of websites; because the cost of hosting is virtually free until someone accesses the site. Cost does not equate simulation space - it’s based on simultaneous concurrent accesses and the complexity of processing the requests.

OpenSim falls into the same trap in many ways - while the cost of hosting an empty region is nearly nil; there are two key aspects where processing will always continue even if there is no need or desire to do so. These areas are physics and scripting - arguably two of the larger expenses on the processor bill.

Physics can be limited somewhat - switching away from a persistent simulator (ODE) to something that computes physics ‘on demand’ (POS, BasicPhysics) will remove the expense of physics while no-one is in the region, but you lose the ability to have objects move independently. For those hosting geographical areas this may be perfect - if you don’t have any scripts in the region and compute physics purely on demand, you are looking at a raw cost in just memory - about 20mb per region, and even that can be paged to disk safely.

However, hosting conventional regions is a more tricky prospect - users have an expectation of certain features working, people use scripting and want to physically interact with objects. One of the options worth considering may be simply dialling the simFPS according to the number of viewers in the region. Drop down to 1Hz when there is no users, but dial back up to 45Hz when users appear - all easy enough to do within the codebase, however doesn’t reduce the processor cost to zero while inactive.

If we consider the ultimate goal being to reduce Virtual World running expenses to similar to that of a web-host: costs being per-access, measured in processor time, bandwidth, etc. then we need to go a few steps further. One of the bigger steps is reducing expectations - right now you can safely assume LSL will always be running, so therefor you can write things like “servers” in LSL. Servers are a good example of the problem - they are something that interacts with the world, but aren’t supposed to be part of it; yet they consume the expenses of being in the world all the same.

Servers could be much better replaced by simple web scripts or server daemons on a normal server - which have a decent API that can connect to the world and make their interactions without needing to be part of it. By doing so, you not only make the servers more efficient (Apache+PHP is faster and more powerful than LSL), but you reduce the persistent load on the world itself.

The work I am doing on MRM is addressing part of this problem - redefining the API to reduce the number of scripts you need in the world, but a total solution here includes some kind of “remoting-style” API that lets you send messages and interact with the world, from a completely independent outside authority. The other side of the same coin is reducing ‘background noise’ processing - timers, sensorrepeats and other recurring tasks all place a small but visible background load on the server, all of these events will keep the server processing even if there is nothing to do.

Some things may require this - but encouraging people to think about when they need these events is better. Limitations on the LSL API really prevent this in SL, but in OpenSim would you be willing to use a “TimerIfAvatarInRegion” instead of a plain Timer? If you could - then it would allow the back-end server to attach conditions to your scheduler which provide optimisations when no-one is there. Allowing these kinds of optimizations is going to be key in the long term - because a cost of one processor core per four concurrent users is just simply insane and will never be adopted in the wider marketplace VW operators hope to gain. If webservers could only handle four simultaneous users - Google would require millions of servers to operate instead of just thousands.

3 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 11th, 2009 at 7:51 am

Posted in OpenSim

Tagged with , ,

MRM Micropost: Keyword Rename

without comments

//MiniMod:C# no longer is the MRM keyword, the new keyword is //MRM:C#

That is all.

0 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 11th, 2009 at 7:24 am

Posted in Uncategorized

Tagged with , ,

MRM Micropost: �Type� via �is�

without comments

Determining the type of object returned via a sensor or other detection event (eg collision, etc) in LSL is done via llDetectedType() - this returns a bitflags containing whether the object is an avatar, prim, etc.

Under MRM, the same is achieved by using the C# keyword “is”. In C# this returns true if the object is a specific type, or implements the interface ‘type’; because of this it means that we can determine what an IEntity is by looking for the inherited classes.

For example:

In this example, e.Sender is defined to be an IEntity - which can mean an Object or an Avatar presently (there may be other types of entity potentially later on). You can determine exactly what type of entity using “is IObject” or “is IAvatar”, and if it returns true, you can typecast to those interfaces safely.

3 Vote

Feedback

If you found this post useful and want me to write more on this topic, please use the vote button to the left or leave me a comment.

Written by Adam Frisby

April 10th, 2009 at 6:48 am

Posted in OpenSim

Tagged with , ,

 

You need to log in to vote

The blog owner requires users to be logged in to be able to vote for this post.

Alternatively, if you do not have an account yet you can create one here.

Powered by Vote It Up