Adam Frisby introduces the next generation scripting in Opensim. MRM or Mini Region Module provides a C# based interface for scripting - an alternative to LSL/OSSL.
Scripting OpenSim right now is a chore for the seasoned
developer - there's very few options sitting between 'write a
plugin', and the LSL/OSSL implementation currently in place. For
reasons I wont go into too much detail here, LSL is badly designed
- the API in particular places too much emphasis on restricting the
programmer rather than empowering them.
While Region Modules are exceptionally powerful, and quite
capable of doing all that LSL can (and lots more), they require the
programmer shut down the sim and restart it between tests of the
module, resulting in a significant loss of productivity. MRM
Scripting aims to fix this - MRM is short for 'Mini Region Module',
and is something I have been adding silently to the OpenSim SVN for
the last month. The goal is a very clean documented API similar to
a full region module, but includes the ability to add in security
features and also compile and edit the modules without shutting
down the sim.
MRM Modules are written in C# (like OpenSim itself), but unlike
the currently implemented C# engine, contain a vastly different
more object-oriented API. It's probably best illustrated with a
couple of examples - below is the obligatory 'Hello World' as a MRM
module.
Hello World in MRM
//MiniMod:C#
using OpenSim.Region.OptionalModules.Scripting.Minimodule;
namespace OpenSim
{
class MiniModule : MRMBase
{
public override void Start()
{
Host.Console.Info("Hello World!");
}
public override void Stop()
{
}
}
}
As you can see, the entrypoints to an application are the
Start() and Stop() events. Unlike LSL/OSSL, you wont recieve an
'event' automatically just by declaring the function. Like
conventional OpenSimulator region modules, you need to explicitly
declare which events you want to listen to via standard C# event
syntax.
...
public override void Start()
{
World.OnFrame += MyOnFrame;
}
public void MyOnFrame()
{
// Do something here which occurs each frame
}
...
The result is fairly clean - the script engine only needs to
give you information that you request, rather than send the event
at runtime, only to have it ignored. It also gives you the ability
to selectively listen only when you want (by binding and unbinding
on demand.). The largest reason for this however, is because of
scope - MRM has a much wider scope than LSL/OSSL.
Where on the Toolchain?
MRM's fill a niche in the tool chain between end-user scripting
and region modules, while we can secure MRMs (and plan on doing
so), they are designed for 'World Builders' who want reasonable
amounts of power, and know the repercussions for abusing it (ie,
lag, etc). They fit somewhere between OSSL and Region Modules -
sharing many of the advantages of both.

To summarise this in a somewhat incomplete table of features,
the scope of a MRM can be seen below

The Scope of the Script
Under LSL, your scope is limited to the Primitive the script is
hosted in, with some very limited exceptions to say objects in the
same link set. There is absolutely no ability whatsoever to listen
for events affecting another object, unless that object also
contains a script which can communicate with yours. MRM by
comparison lives somewhere in the 'World', and consequently
contains a much wider 'Scope'. This means, if you want to listen to
the touch event on any object in the world, it is quite possible to
do.
...
public override void Start()
{
foreach(IObject obj in World.Objects) {
obj.OnTouch += MyOnTouch;
}
}
public void MyOnTouch(IObject sender, TouchEventArgs e)
{
// Do something here
}
...
The above example demonstrates some of the power of the MRM API,
the LSL equivilent would require a script in every single one of
the objects in the region.
Hosted Scripts
The final point worth noting is that MRM can act as a complete
replacement for LSL - a script which for example changes the color
of the object it is located in, can be implemented via the Host.
Host contains a member called 'Object', which dictates the object
that the MRM Script resides in. Host.Object conforms to the same
IObject interface as World.Objects[], so any function can be done
on both the host and remote objects.
Final Notes, Enabling, Security, etc.
The MRM API is presently incomplete, the largest sections
currently undesigned relate to events and callbacks. The currently
implemented versions (SOPObject.cs, World.cs, etc) are missing
functionality, but you can still do some reasonably nifty things
with it. Just dont expect this to be a fully ready replacement
until we've implemented all the members correctly. It's also worth
noting that any MRM compile errors will disconnect your client from
the sim, this is a bug and will be fixed. The API however should be
100% capable of wrapping LSL/OSSL functionality - infact it should
be possible to write a LSL2MRM cross-compiler (Part of this comes
from my
discussions with Jim Purbrick about distilling LSL to a simple
set of interfaces).
MRM can be enabled via the [MRM] section of the OpenSim.ini,
however it is strongly recommended that you be wary with
this on a public environment. Presently any MRM script has
access to the complete .NET API, this means it would be possible to
compile a script calling for your server disk to be formatted. I
recommend using this in offline standalone regions only for the
moment. Proper security is part of the design, however is currently
unimplemented. There is also a few functions which are implemented
badly and may cause lag if used repeatably, all on the agenda for
being fixed before we hit a beta version.