MRM Scripting – Coming to OpenSim soon!
(cross-posted from Adam Frisby’s blog)
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.